Element-React Tree 樹形控件

2020-10-16 11:32 更新

用清晰的層級結構展示信息,可展開或折疊。

基礎用法

基礎的樹形結構展示。

constructor(props) {
  super(props);


  this.state = {
    data: [{
      label: '一級 1',
      children: [{
        label: '二級 1-1',
        children: [{
          label: '三級 1-1-1'
        }]
      }]
    }, {
      label: '一級 2',
      children: [{
        label: '二級 2-1',
        children: [{
          label: '三級 2-1-1'
        }]
      }, {
        label: '二級 2-2',
        children: [{
          label: '三級 2-2-1'
        }]
      }]
    }, {
      label: '一級 3',
      children: [{
        label: '二級 3-1',
        children: [{
          label: '三級 3-1-1'
        }]
      }, {
        label: '二級 3-2',
        children: [{
          label: '三級 3-2-1'
        }]
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
}


render() {
  return (
    <Tree
      data={this.state.data}
      options={this.state.options}
      highlightCurrent={true}
      onCheckChange={(data, checked, indeterminate)=>{
        console.debug('onCheckChange: ', data, checked, indeterminate)}
      }
      onNodeClicked={(data, reactElement,)=>{
        console.debug('onNodeClicked: ', data, reactElement)
      }}
    />
  )
}

可選擇

適用于需要選擇層級時使用。在下例中,由于在點擊時才進行該層數(shù)據(jù)的獲取,導致層級不可預知,如果沒有下層數(shù)據(jù),則點擊后下拉按鈕會消失。

constructor(props) {
  super(props)
  this.state = {
    regions: [{
      'name': 'region1'
    }, {
      'name': 'region2'
    }]
  }


  this.options = {
    label: 'name',
    children: 'zones'
  }
  this.count = 1


}


handleCheckChange(data, checked, indeterminate) {
  console.log(data, checked, indeterminate);
}


loadNode(node, resolve) {


  if (node.level === 0) {
    return resolve([{ name: 'region1' }, { name: 'region2' }]);
  }
  if (node.level > 3) return resolve([]);


  var hasChild;
  if (node.data.name === 'region1') {
    hasChild = true;
  } else if (node.data.name === 'region2') {
    hasChild = false;
  } else {
    hasChild = Math.random() > 0.5;
  }


  setTimeout(() => {
    var data;
    if (hasChild) {
      data = [{
        name: 'zone' + this.count++
      }, {
        name: 'zone' + this.count++
      }];
    } else {
      data = [];
    }


    resolve(data);
  }, 500);
}


render() {
  const { regions } = this.state


  return (
    <Tree
      data={regions}
      options={this.options}
      isShowCheckbox={true}
      lazy={true}
      load={this.loadNode.bind(this)}
      onCheckChange={this.handleCheckChange.bind(this)}
      onNodeClicked={(data, nodeModel, reactElement, treeNode)=>{
        console.debug('onNodeClicked: ', data, nodeModel, reactElement)
      }}
    />
  )
}

默認展開和默認選中

可將 Tree 的某些節(jié)點設置為默認展開或默認選中

分別通過defaultExpandedKeysdefaultCheckedKeys設置默認展開和默認選中的節(jié)點。需要注意的是,此時必須設置nodeKey,其值為節(jié)點數(shù)據(jù)中的一個字段名,該字段在整棵樹中是唯一的。

constructor(props) {
  super(props);


  this.state = {
    data: [{
      id: 1,
      label: '一級 1',
      children: [{
        id: 4,
        label: '二級 1-1',
        children: [{
          id: 9,
          label: '三級 1-1-1'
        }, {
          id: 10,
          label: '三級 1-1-2'
        }]
      }]
    }, {
      id: 2,
      label: '一級 2',
      children: [{
        id: 5,
        label: '二級 2-1'
      }, {
        id: 6,
        label: '二級 2-2'
      }]
    }, {
      id: 3,
      label: '一級 3',
      children: [{
        id: 7,
        label: '二級 3-1'
      }, {
        id: 8,
        label: '二級 3-2'
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
}


render() {
  const { data, options } = this.state


  return (
    <Tree
      data={data}
      options={options}
      isShowCheckbox={true}
      nodeKey="id"
      defaultExpandedKeys={[2, 3]}
      defaultCheckedKeys={[5]}
    />
  )
}

樹節(jié)點的選擇

通過 node 獲取通過 key 獲取通過 node 設置通過 key 設置清空

本例展示如何獲取和設置選中節(jié)點。獲取和設置各有兩種方式:通過 node 或通過 key。如果需要通過 key 來獲取或設置,則必須設置nodeKey。

constructor(props) {
  super(props);


  this.state = {
    data: [{
      id: 1,
      label: '一級 1',
      children: [{
        id: 4,
        label: '二級 1-1',
        children: [{
          id: 9,
          label: '三級 1-1-1'
        }, {
          id: 10,
          label: '三級 1-1-2'
        }]
      }]
    }, {
      id: 2,
      label: '一級 2',
      children: [{
        id: 5,
        label: '二級 2-1'
      }, {
        id: 6,
        label: '二級 2-2'
      }]
    }, {
      id: 3,
      label: '一級 3',
      children: [{
        id: 7,
        label: '二級 3-1'
      }, {
        id: 8,
        label: '二級 3-2'
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
}


getCheckedNodes() {
  console.log(this.tree.getCheckedNodes());
}
getCheckedKeys() {
  console.log(this.tree.getCheckedKeys());
}
setCheckedNodes() {
  this.tree.setCheckedNodes([{
    id: 5,
    label: '二級 2-1'
  }, {
    id: 9,
    label: '三級 1-1-1'
  }]);
}
setCheckedKeys() {
  this.tree.setCheckedKeys([3]);
}
resetChecked() {
  this.tree.setCheckedKeys([]);
}


render() {
  const { data, options } = this.state


  return (
    <div>
      <Tree
        ref={e=>this.tree = e}
        data={data}
        options={options}
        isShowCheckbox={true}
        highlightCurrent={true}
        nodeKey="id"
        defaultExpandedKeys={[2, 3]}
        defaultCheckedKeys={[5]}
      />
      <div className="buttons">
        <Button onClick={()=>this.getCheckedNodes()}>通過 node 獲取</Button>
        <Button onClick={()=>this.getCheckedKeys()}>通過 key 獲取</Button>
        <Button onClick={()=>this.setCheckedNodes()}>通過 node 設置</Button>
        <Button onClick={()=>this.setCheckedKeys()}>通過 key 設置</Button>
        <Button onClick={()=>this.resetChecked()}>清空</Button>
      </div>
    </div>
  )
}

自定義節(jié)點內(nèi)容

節(jié)點的內(nèi)容支持自定義,可以在節(jié)點區(qū)添加按鈕或圖標等內(nèi)容

使用renderContent指定渲染函數(shù),該函數(shù)返回需要的節(jié)點區(qū)內(nèi)容即可。渲染函數(shù)的用法請參考 Vue 文檔。注意:由于 jsfiddle 不支持 JSX 語法,所以本例在 jsfiddle 中無法運行。但是在實際的項目中,只要正確地配置了相關依賴,就可以正常運行。

constructor(props) {
  super(props);


  this.state = {
    data: [{
      id: 1,
      label: '一級 1',
      children: [{
        id: 4,
        label: '二級 1-1',
        children: [{
          id: 9,
          label: '三級 1-1-1'
        }, {
          id: 10,
          label: '三級 1-1-2'
        }]
      }]
    }, {
      id: 2,
      label: '一級 2',
      children: [{
        id: 5,
        label: '二級 2-1'
      }, {
        id: 6,
        label: '二級 2-2'
      }]
    }, {
      id: 3,
      label: '一級 3',
      children: [{
        id: 7,
        label: '二級 3-1'
      }, {
        id: 8,
        label: '二級 3-2'
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
  this.id = 100;
}


append(store, data) {
  store.append({ id: this.id++, label: `testtest_${this.id}`, children: [] }, data);
}


remove(store, data) {
  store.remove(data);
}


renderContent(nodeModel, data, store) {
  return (
    <span>
      <span>
        <span>{data.label}</span>
      </span>
      <span style={{float: 'right', marginRight: '20px'}}>
        <Button size="mini" onClick={ () => this.append(store, data) }>Append</Button>
        <Button size="mini" onClick={ () => this.remove(store, data) }>Delete</Button>
      </span>
    </span>);
}


render() {
  const { data, options } = this.state


  return (
    <Tree
      data={data}
      options={options}
      isShowCheckbox={true}
      nodeKey="id"
      defaultExpandAll={true}
      expandOnClickNode={false}
      renderContent={(...args)=>this.renderContent(...args)}
    />
  )
}

節(jié)點過濾

通過關鍵字過濾樹節(jié)點

在需要對節(jié)點進行過濾時,調(diào)用 Tree 實例的filter方法,參數(shù)為關鍵字。需要注意的是,此時需要設置filterNodeMethod,值為過濾函數(shù)。

constructor(props) {
  super(props);


  this.state = {
    data: [{
      id: 1,
      label: '一級 1',
      children: [{
        id: 4,
        label: '二級 1-1',
        children: [{
          id: 9,
          label: '三級 1-1-1'
        }, {
          id: 10,
          label: '三級 1-1-2'
        }]
      }]
    }, {
      id: 2,
      label: '一級 2',
      children: [{
        id: 5,
        label: '二級 2-1'
      }, {
        id: 6,
        label: '二級 2-2'
      }]
    }, {
      id: 3,
      label: '一級 3',
      children: [{
        id: 7,
        label: '二級 3-1'
      }, {
        id: 8,
        label: '二級 3-2'
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
}


render() {
  const { data, options } = this.state


  return (
    <div>
      <Input placeholder="輸入關鍵字進行過濾" onChange={text=> this.tree.filter(text)} />
      <Tree
        ref={e=> this.tree = e}
        className="filter-tree"
        data={data}
        options={options}
        nodeKey="id"
        defaultExpandAll={true}
        filterNodeMethod={(value, data)=>{
          if (!value) return true;
          return data.label.indexOf(value) !== -1;
        }}
      />
    </div>


  )
}

手風琴模式

對于同一級的節(jié)點,每次只能展開一個

constructor(props) {
  super(props);


  this.state = {
    data: [{
      label: '一級 1',
      children: [{
        label: '二級 1-1',
        children: [{
          label: '三級 1-1-1'
        }]
      }]
    }, {
      label: '一級 2',
      children: [{
        label: '二級 2-1',
        children: [{
          label: '三級 2-1-1'
        }]
      }, {
        label: '二級 2-2',
        children: [{
          label: '三級 2-2-1'
        }]
      }]
    }, {
      label: '一級 3',
      children: [{
        label: '二級 3-1',
        children: [{
          label: '三級 3-1-1'
        }]
      }, {
        label: '二級 3-2',
        children: [{
          label: '三級 3-2-1'
        }]
      }]
    }],
    options: {
      children: 'children',
      label: 'label'
    }
  }
}


render() {
  const { data, options } = this.state


  return (
    <Tree
      ref={e=> this.tree = e}
      data={data}
      options={options}
      accordion={true}
      onNodeClicked={node=>console.log(node)}
    />
  )
}

Attributes

參數(shù) 說明 類型 可選值 默認值
data 展示數(shù)據(jù) array
emptyText 內(nèi)容為空的時候展示的文本 String
nodeKey 每個樹節(jié)點用來作為唯一標識的屬性,整顆樹應該是唯一的 String
options 配置選項,具體看下表 object
load 加載子樹數(shù)據(jù)的方法 function(node, resolve)
renderContent 樹節(jié)點的內(nèi)容區(qū)的渲染 Function (nodeModel, data, store)=>ReactElement
highlightCurrent 是否高亮當前選中節(jié)點,默認值是 false。 boolean false
currentNodeKey 當前選中節(jié)點的 key,只寫屬性 string, number
defaultExpandAll 是否默認展開所有節(jié)點 boolean false
expandOnClickNode 是否在點擊節(jié)點的時候展開或者收縮節(jié)點, 默認值為 true,如果為 false,則只有點箭頭圖標的時候才會展開或者收縮節(jié)點。 boolean true
autoExpandParent 展開子節(jié)點的時候是否自動展開父節(jié)點 boolean true
defaultExpandedKeys 默認展開的節(jié)點的 key 的數(shù)組 array
isShowCheckbox 節(jié)點是否可被選擇 boolean false
checkedKeyStrictly 在顯示復選框的情況下,是否嚴格的遵循父子不互相關聯(lián)的做法,默認為 false boolean false
defaultCheckedKeys 默認勾選的節(jié)點的 key 的數(shù)組 array
filterNodeMethod 對樹節(jié)點進行篩選時執(zhí)行的方法,返回 true 表示這個節(jié)點可以顯示,返回 false 則表示這個節(jié)點會被隱藏 Function(value, data, node)
accordion 是否每次只打開一個同級樹節(jié)點展開 boolean false
indent 相鄰級節(jié)點間的水平縮進,單位為像素 number 16

options

參數(shù) 說明 類型 可選值 默認值
label 指定節(jié)點標簽為節(jié)點對象的某個屬性值 string
children 指定子樹為節(jié)點對象的某個屬性值 string

方法

Tree 擁有如下方法,返回目前被選中的節(jié)點數(shù)組:

方法名 說明 參數(shù)
filter 對樹節(jié)點進行篩選操作 接收一個任意類型的參數(shù),該參數(shù)會在 filterNodeMethod 中作為第一個參數(shù)
getCheckedNodes 若節(jié)點可被選擇(即 isShowCheckbox 為 true),則返回目前被選中的節(jié)點所組成的數(shù)組 (leafOnly) 接收一個 boolean 類型的參數(shù),若為 true 則僅返回被選中的葉子節(jié)點,默認值為 false
setCheckedNodes 設置目前勾選的節(jié)點,使用此方法必須設置 nodeKey 屬性 (nodes) 接收勾選節(jié)點數(shù)據(jù)的數(shù)組
getCheckedKeys 若節(jié)點可被選擇(即 isShowCheckbox 為 true),則返回目前被選中的節(jié)點所組成的數(shù)組 (leafOnly) 接收一個 boolean 類型的參數(shù),若為 true 則僅返回被選中的葉子節(jié)點的 keys,默認值為 false
setCheckedKeys 通過 keys 設置目前勾選的節(jié)點,使用此方法必須設置 nodeKey 屬性 (keys, leafOnly) 接收兩個參數(shù),1. 勾選節(jié)點的 key 的數(shù)組 2. boolean 類型的參數(shù),若為 true 則僅設置葉子節(jié)點的選中狀態(tài),默認值為 false
setChecked 通過 key / data 設置某個節(jié)點的勾選狀態(tài),使用此方法必須設置 nodeKey 屬性 (key/data, checked, deep) 接收三個參數(shù),1. 勾選節(jié)點的 key 或者 data 2. boolean 類型,節(jié)點是否選中 3. boolean 類型,是否設置子節(jié)點 ,默認為 false

Events

事件名稱 說明 回調(diào)參數(shù)
onNodeClicked 節(jié)點被點擊時的回調(diào) onNodeClicked(nodeModel.data, node)
onCheckChange 節(jié)點選中狀態(tài)發(fā)生變化時的回調(diào) onCheckChange(nodeModel.data, checked, indeterminate)
onCurrentChange 當前選中節(jié)點變化時觸發(fā)的事件 onCurrentChange(nodeModel.data, node)
onNodeExpand 節(jié)點被展開時觸發(fā)的事件 onNodeExpand(nodeModel.data, nodeModel, node)
onNodeCollapse 節(jié)點被關閉時觸發(fā)的事件 onNodeCollapse(nodeModel.data, nodeModel, node)

參數(shù)說明

參數(shù) 說明
nodeModel tree node 的 model
nodeModel.data 對應的tree node節(jié)點的傳入的data節(jié)點
node 實際的view層的react element節(jié)點
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號