1. 程式人生 > 程式設計 >Ant Design的可編輯Tree的實現操作

Ant Design的可編輯Tree的實現操作

前言

最近在用Ant Design寫一個後臺,遇到的需求就是實現一個可動態增減和編輯子節點的Tree。GitHub上看了一圈,沒好用和合適的。索性就基於Ant Design中的Tree元件寫一個。

實現的效果如下:

可以增加子節點

可以刪除子節點

可以編輯子節點資訊

可以取消編輯資訊

具體的效果圖如下:

Ant Design的可編輯Tree的實現操作

主要的就是藉助 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 也是極好的。

補充知識:關於antd Select 限制選擇個數的解決方案

應用場景描述:

Select 被form 所包裹,且被getFieldDecorator修飾。所以值的改變應該通過form的setFieldsValue方法。

Select模式肯定會是multiple。且以最多三個值舉例。

解決思路如下:

1 起初是想在Select的onchange事件中判斷values的數量,數量大於三個的時候來重新setFieldsValue;且把最後的選項值替換成剛剛選擇的值。

後來發現setFieldsValue方法不起作用,Select的值會一直增加。後來想想可能是 setFieldsValue與onchange 衝突,通過setFieldsValue 無法改變onchange後的值。

2 最後通過重新檢視文件。發現還有一個方法可用,即 validator。驗證值,通過驗證所選值的數量是否大於三個,然後重新setFieldsValue ;發現此法可行。從而解決該疑難雜症。

好,最後附上程式碼供參考:

changeValues = (rule,value,callback)=> {
  const { setFieldsValue } = this.props.form ;
  let newArr ;
  if (value.length > 3){
    newArr = [].concat(value.slice(0,2),value.slice(-1) ) ;
    setFieldsValue({
    "languages" : newArr,    })
    callback('最多選擇三種語言')
  } else {
    newArr = value ;
    callback()
  }
}
 
<FormItem>
{getFieldDecorator('languages',{
rules:[{required: true,message : '請選擇三種語言',validator : changeValues
}],validateTrigger : 'onChange',})(
<Select mode='multiple' >
 
  <Option key={1} value={1}>1</Option>
  <Option key={2} value={2}>2</Option>
   <Option key={3} value={3}>3</Option>
  <Option key={4} value={4}>4</Option>
  <Option key={5} value={5}>5</Option>
</Select>
)}
</FormItem>

以上這篇Ant Design的可編輯Tree的實現操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。