Реализация редактируемого дерева на основе Ant Design

React.js Ant Design

предисловие

Недавно я писал бэкенд с помощью Ant Design, и столкнулся с требованием реализовать дерево, которое может динамически увеличивать, уменьшать и редактировать дочерние узлы. Я посмотрел на GitHub, и он не был простым в использовании и подходящим. Просто напишите его на основе компонента Tree в Ant Design. Достигаемый эффект следующий:

  • можно добавить дочерние узлы
  • дочерние узлы могут быть удалены
  • Может редактировать информацию о дочернем узле
  • Может отменить редактирование информации

Конкретная схема эффекта выглядит следующим образом:

screenshots

Главное использоватьTreeNodeизtitleсвойство, его типstring|ReactNode.

текст

После анализа структура данных узла должна быть

{
    value: 'Root', // 显示的信息
    defaultValue: 'Root', // 当某一节点进入编辑状态,然后点击close按钮,节点的信息应该恢复原始状态,
    key: '0-1', // 节点的Key,全局唯一
    parentKey: '0', // 父节点的Key
    isEditable: false // 是否处于可编辑状态
    children:[] // 子节点
}

Сборка через структуры данныхTreeNodeКод выглядит следующим образом:

    data= [
      {
        value: 'Root',
        defaultValue: 'Root',
        key: '0-1',
        parentKey: '0',
        isEditable: false
      }
    ];
    
    state={
        data: this.data
    }


renderTreeNodes = data => data.map((item) => {
    if (item.isEditable) {  // 编辑状态下
      item.title = (
        <div>
          <input value={item.value}
            onChange={(e) => this.onChange(e, item.key)}/>
          <Icon type='close'  style={{marginLeft:10}} onClick={() => this.onClose(item.key, item.defaultValue)}/>
          <Icon type='check'  style={{marginLeft:10}} onClick={() => this.onSave(item.key)}/>
        </div>
      );
    } else {
      item.title = (
        <div>
          <span>
            {item.value}
          </span>
          <Icon style={{ marginLeft: 10 }} type='edit' onClick={() => this.onEdit(item.key)} />
          <Icon style={{ marginLeft: 10 }} type='plus' onClick={() => this.onAdd(item.key)} />
          {item.parentKey === '0' ? null : (<Icon style={{ marginLeft: 10 }} type='minus' onClick={() => this.onDelete(item.key)} />)}  // 根节点没有删除按钮
        </div>
      )
    }

    if (item.children) {
      return (
        <TreeNode title={item.title} key={item.key} dataRef={item}>
          {this.renderTreeNodes(item.children)}
        </TreeNode>
      );
    }

    return <TreeNode {...item}/>;
  })
  
  ...
  
  // 渲染界面
  render() {
    return (
      <div>
        <Tree>
          {this.renderTreeNodes(this.state.data)}
        </Tree>
      </div>
    )
  }

Все последующие добавления, удаления, модификации и т. д. изменяются в первую очередьdataданные в этом массиве, а затем используйтеthis.setState({ data: this.data })Обновите интерфейс, просто посмотрите на код, это очень просто.

При окончательной оптимизации этого компонента я столкнулся с ямой. Первоначально считалось, что когда дочерний узел добавляется к узлу, родительский узел автоматически расширяется, и нет проблем с логикой кода, но логика должна выполняться вручную один раз, чтобы расширить или найти написанную логику, чтобы она вступила в силу. Позже другого пути нет, но его можно активировать только после загрузки DOM в функции жизненного цикла:

componentDidMount() {
    this.onExpand([]); // 手动触发,否则会遇到第一次添加子节点不展开的Bug
  }

Код находится на GitHub по адресуreact-editable-tree, Добро пожаловать в ссылку небольших партнеров, которые имеют такие же потребности,starа такжеforkТоже отлично.