Element-React Tree 樹形控件

2020-10-16 11:32 更新

用清晰的層級結(jié)構(gòu)展示信息,可展開或折疊。

基礎(chǔ)用法

基礎(chǔ)的樹形結(jié)構(gòu)展示。

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. label: '一級 1',
  6. children: [{
  7. label: '二級 1-1',
  8. children: [{
  9. label: '三級 1-1-1'
  10. }]
  11. }]
  12. }, {
  13. label: '一級 2',
  14. children: [{
  15. label: '二級 2-1',
  16. children: [{
  17. label: '三級 2-1-1'
  18. }]
  19. }, {
  20. label: '二級 2-2',
  21. children: [{
  22. label: '三級 2-2-1'
  23. }]
  24. }]
  25. }, {
  26. label: '一級 3',
  27. children: [{
  28. label: '二級 3-1',
  29. children: [{
  30. label: '三級 3-1-1'
  31. }]
  32. }, {
  33. label: '二級 3-2',
  34. children: [{
  35. label: '三級 3-2-1'
  36. }]
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. }
  45. render() {
  46. return (
  47. <Tree
  48. data={this.state.data}
  49. options={this.state.options}
  50. highlightCurrent={true}
  51. onCheckChange={(data, checked, indeterminate)=>{
  52. console.debug('onCheckChange: ', data, checked, indeterminate)}
  53. }
  54. onNodeClicked={(data, reactElement,)=>{
  55. console.debug('onNodeClicked: ', data, reactElement)
  56. }}
  57. />
  58. )
  59. }

可選擇

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

  1. constructor(props) {
  2. super(props)
  3. this.state = {
  4. regions: [{
  5. 'name': 'region1'
  6. }, {
  7. 'name': 'region2'
  8. }]
  9. }
  10. this.options = {
  11. label: 'name',
  12. children: 'zones'
  13. }
  14. this.count = 1
  15. }
  16. handleCheckChange(data, checked, indeterminate) {
  17. console.log(data, checked, indeterminate);
  18. }
  19. loadNode(node, resolve) {
  20. if (node.level === 0) {
  21. return resolve([{ name: 'region1' }, { name: 'region2' }]);
  22. }
  23. if (node.level > 3) return resolve([]);
  24. var hasChild;
  25. if (node.data.name === 'region1') {
  26. hasChild = true;
  27. } else if (node.data.name === 'region2') {
  28. hasChild = false;
  29. } else {
  30. hasChild = Math.random() > 0.5;
  31. }
  32. setTimeout(() => {
  33. var data;
  34. if (hasChild) {
  35. data = [{
  36. name: 'zone' + this.count++
  37. }, {
  38. name: 'zone' + this.count++
  39. }];
  40. } else {
  41. data = [];
  42. }
  43. resolve(data);
  44. }, 500);
  45. }
  46. render() {
  47. const { regions } = this.state
  48. return (
  49. <Tree
  50. data={regions}
  51. options={this.options}
  52. isShowCheckbox={true}
  53. lazy={true}
  54. load={this.loadNode.bind(this)}
  55. onCheckChange={this.handleCheckChange.bind(this)}
  56. onNodeClicked={(data, nodeModel, reactElement, treeNode)=>{
  57. console.debug('onNodeClicked: ', data, nodeModel, reactElement)
  58. }}
  59. />
  60. )
  61. }

默認展開和默認選中

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

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

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. id: 1,
  6. label: '一級 1',
  7. children: [{
  8. id: 4,
  9. label: '二級 1-1',
  10. children: [{
  11. id: 9,
  12. label: '三級 1-1-1'
  13. }, {
  14. id: 10,
  15. label: '三級 1-1-2'
  16. }]
  17. }]
  18. }, {
  19. id: 2,
  20. label: '一級 2',
  21. children: [{
  22. id: 5,
  23. label: '二級 2-1'
  24. }, {
  25. id: 6,
  26. label: '二級 2-2'
  27. }]
  28. }, {
  29. id: 3,
  30. label: '一級 3',
  31. children: [{
  32. id: 7,
  33. label: '二級 3-1'
  34. }, {
  35. id: 8,
  36. label: '二級 3-2'
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. }
  45. render() {
  46. const { data, options } = this.state
  47. return (
  48. <Tree
  49. data={data}
  50. options={options}
  51. isShowCheckbox={true}
  52. nodeKey="id"
  53. defaultExpandedKeys={[2, 3]}
  54. defaultCheckedKeys={[5]}
  55. />
  56. )
  57. }

樹節(jié)點的選擇

通過 node 獲取通過 key 獲取通過 node 設(shè)置通過 key 設(shè)置清空

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

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. id: 1,
  6. label: '一級 1',
  7. children: [{
  8. id: 4,
  9. label: '二級 1-1',
  10. children: [{
  11. id: 9,
  12. label: '三級 1-1-1'
  13. }, {
  14. id: 10,
  15. label: '三級 1-1-2'
  16. }]
  17. }]
  18. }, {
  19. id: 2,
  20. label: '一級 2',
  21. children: [{
  22. id: 5,
  23. label: '二級 2-1'
  24. }, {
  25. id: 6,
  26. label: '二級 2-2'
  27. }]
  28. }, {
  29. id: 3,
  30. label: '一級 3',
  31. children: [{
  32. id: 7,
  33. label: '二級 3-1'
  34. }, {
  35. id: 8,
  36. label: '二級 3-2'
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. }
  45. getCheckedNodes() {
  46. console.log(this.tree.getCheckedNodes());
  47. }
  48. getCheckedKeys() {
  49. console.log(this.tree.getCheckedKeys());
  50. }
  51. setCheckedNodes() {
  52. this.tree.setCheckedNodes([{
  53. id: 5,
  54. label: '二級 2-1'
  55. }, {
  56. id: 9,
  57. label: '三級 1-1-1'
  58. }]);
  59. }
  60. setCheckedKeys() {
  61. this.tree.setCheckedKeys([3]);
  62. }
  63. resetChecked() {
  64. this.tree.setCheckedKeys([]);
  65. }
  66. render() {
  67. const { data, options } = this.state
  68. return (
  69. <div>
  70. <Tree
  71. ref={e=>this.tree = e}
  72. data={data}
  73. options={options}
  74. isShowCheckbox={true}
  75. highlightCurrent={true}
  76. nodeKey="id"
  77. defaultExpandedKeys={[2, 3]}
  78. defaultCheckedKeys={[5]}
  79. />
  80. <div className="buttons">
  81. <Button onClick={()=>this.getCheckedNodes()}>通過 node 獲取</Button>
  82. <Button onClick={()=>this.getCheckedKeys()}>通過 key 獲取</Button>
  83. <Button onClick={()=>this.setCheckedNodes()}>通過 node 設(shè)置</Button>
  84. <Button onClick={()=>this.setCheckedKeys()}>通過 key 設(shè)置</Button>
  85. <Button onClick={()=>this.resetChecked()}>清空</Button>
  86. </div>
  87. </div>
  88. )
  89. }

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

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

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

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. id: 1,
  6. label: '一級 1',
  7. children: [{
  8. id: 4,
  9. label: '二級 1-1',
  10. children: [{
  11. id: 9,
  12. label: '三級 1-1-1'
  13. }, {
  14. id: 10,
  15. label: '三級 1-1-2'
  16. }]
  17. }]
  18. }, {
  19. id: 2,
  20. label: '一級 2',
  21. children: [{
  22. id: 5,
  23. label: '二級 2-1'
  24. }, {
  25. id: 6,
  26. label: '二級 2-2'
  27. }]
  28. }, {
  29. id: 3,
  30. label: '一級 3',
  31. children: [{
  32. id: 7,
  33. label: '二級 3-1'
  34. }, {
  35. id: 8,
  36. label: '二級 3-2'
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. this.id = 100;
  45. }
  46. append(store, data) {
  47. store.append({ id: this.id++, label: `testtest_${this.id}`, children: [] }, data);
  48. }
  49. remove(store, data) {
  50. store.remove(data);
  51. }
  52. renderContent(nodeModel, data, store) {
  53. return (
  54. <span>
  55. <span>
  56. <span>{data.label}</span>
  57. </span>
  58. <span style={{float: 'right', marginRight: '20px'}}>
  59. <Button size="mini" onClick={ () => this.append(store, data) }>Append</Button>
  60. <Button size="mini" onClick={ () => this.remove(store, data) }>Delete</Button>
  61. </span>
  62. </span>);
  63. }
  64. render() {
  65. const { data, options } = this.state
  66. return (
  67. <Tree
  68. data={data}
  69. options={options}
  70. isShowCheckbox={true}
  71. nodeKey="id"
  72. defaultExpandAll={true}
  73. expandOnClickNode={false}
  74. renderContent={(...args)=>this.renderContent(...args)}
  75. />
  76. )
  77. }

節(jié)點過濾

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

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

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. id: 1,
  6. label: '一級 1',
  7. children: [{
  8. id: 4,
  9. label: '二級 1-1',
  10. children: [{
  11. id: 9,
  12. label: '三級 1-1-1'
  13. }, {
  14. id: 10,
  15. label: '三級 1-1-2'
  16. }]
  17. }]
  18. }, {
  19. id: 2,
  20. label: '一級 2',
  21. children: [{
  22. id: 5,
  23. label: '二級 2-1'
  24. }, {
  25. id: 6,
  26. label: '二級 2-2'
  27. }]
  28. }, {
  29. id: 3,
  30. label: '一級 3',
  31. children: [{
  32. id: 7,
  33. label: '二級 3-1'
  34. }, {
  35. id: 8,
  36. label: '二級 3-2'
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. }
  45. render() {
  46. const { data, options } = this.state
  47. return (
  48. <div>
  49. <Input placeholder="輸入關(guān)鍵字進行過濾" onChange={text=> this.tree.filter(text)} />
  50. <Tree
  51. ref={e=> this.tree = e}
  52. className="filter-tree"
  53. data={data}
  54. options={options}
  55. nodeKey="id"
  56. defaultExpandAll={true}
  57. filterNodeMethod={(value, data)=>{
  58. if (!value) return true;
  59. return data.label.indexOf(value) !== -1;
  60. }}
  61. />
  62. </div>
  63. )
  64. }

手風(fēng)琴模式

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

  1. constructor(props) {
  2. super(props);
  3. this.state = {
  4. data: [{
  5. label: '一級 1',
  6. children: [{
  7. label: '二級 1-1',
  8. children: [{
  9. label: '三級 1-1-1'
  10. }]
  11. }]
  12. }, {
  13. label: '一級 2',
  14. children: [{
  15. label: '二級 2-1',
  16. children: [{
  17. label: '三級 2-1-1'
  18. }]
  19. }, {
  20. label: '二級 2-2',
  21. children: [{
  22. label: '三級 2-2-1'
  23. }]
  24. }]
  25. }, {
  26. label: '一級 3',
  27. children: [{
  28. label: '二級 3-1',
  29. children: [{
  30. label: '三級 3-1-1'
  31. }]
  32. }, {
  33. label: '二級 3-2',
  34. children: [{
  35. label: '三級 3-2-1'
  36. }]
  37. }]
  38. }],
  39. options: {
  40. children: 'children',
  41. label: 'label'
  42. }
  43. }
  44. }
  45. render() {
  46. const { data, options } = this.state
  47. return (
  48. <Tree
  49. ref={e=> this.tree = e}
  50. data={data}
  51. options={options}
  52. accordion={true}
  53. onNodeClicked={node=>console.log(node)}
  54. />
  55. )
  56. }

Attributes

參數(shù) 說明 類型 可選值 默認值
data 展示數(shù)據(jù) array
emptyText 內(nèi)容為空的時候展示的文本 String
nodeKey 每個樹節(jié)點用來作為唯一標(biāo)識的屬性,整顆樹應(yīng)該是唯一的 String
options 配置選項,具體看下表 object
load 加載子樹數(shù)據(jù)的方法 function(node, resolve)
renderContent 樹節(jié)點的內(nèi)容區(qū)的渲染 Function (nodeModel, data, store)=>ReactElement
highlightCurrent 是否高亮當(dāng)前選中節(jié)點,默認值是 false。 boolean false
currentNodeKey 當(dāng)前選中節(jié)點的 key,只寫屬性 string, number
defaultExpandAll 是否默認展開所有節(jié)點 boolean false
expandOnClickNode 是否在點擊節(jié)點的時候展開或者收縮節(jié)點, 默認值為 true,如果為 false,則只有點箭頭圖標(biāo)的時候才會展開或者收縮節(jié)點。 boolean true
autoExpandParent 展開子節(jié)點的時候是否自動展開父節(jié)點 boolean true
defaultExpandedKeys 默認展開的節(jié)點的 key 的數(shù)組 array
isShowCheckbox 節(jié)點是否可被選擇 boolean false
checkedKeyStrictly 在顯示復(fù)選框的情況下,是否嚴(yán)格的遵循父子不互相關(guān)聯(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é)點標(biāo)簽為節(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 設(shè)置目前勾選的節(jié)點,使用此方法必須設(shè)置 nodeKey 屬性 (nodes) 接收勾選節(jié)點數(shù)據(jù)的數(shù)組
getCheckedKeys 若節(jié)點可被選擇(即 isShowCheckbox 為 true),則返回目前被選中的節(jié)點所組成的數(shù)組 (leafOnly) 接收一個 boolean 類型的參數(shù),若為 true 則僅返回被選中的葉子節(jié)點的 keys,默認值為 false
setCheckedKeys 通過 keys 設(shè)置目前勾選的節(jié)點,使用此方法必須設(shè)置 nodeKey 屬性 (keys, leafOnly) 接收兩個參數(shù),1. 勾選節(jié)點的 key 的數(shù)組 2. boolean 類型的參數(shù),若為 true 則僅設(shè)置葉子節(jié)點的選中狀態(tài),默認值為 false
setChecked 通過 key / data 設(shè)置某個節(jié)點的勾選狀態(tài),使用此方法必須設(shè)置 nodeKey 屬性 (key/data, checked, deep) 接收三個參數(shù),1. 勾選節(jié)點的 key 或者 data 2. boolean 類型,節(jié)點是否選中 3. boolean 類型,是否設(shè)置子節(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 當(dāng)前選中節(jié)點變化時觸發(fā)的事件 onCurrentChange(nodeModel.data, node)
onNodeExpand 節(jié)點被展開時觸發(fā)的事件 onNodeExpand(nodeModel.data, nodeModel, node)
onNodeCollapse 節(jié)點被關(guān)閉時觸發(fā)的事件 onNodeCollapse(nodeModel.data, nodeModel, node)

參數(shù)說明

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號