Skip to content

Tree 树形控件

介绍

用清晰的层级结构展示信息,可展开或折叠。

TIP

阅读该组件文档前请确保**已认真阅读快速上手章节的每一个字**。

引入

ts
import { IBestTree, IBestTreeController, IBestTreeData, IBestTreeNodeData } from "@ibestservices/ibest-ui-v2";

代码演示

基础用法

按钮类型

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      children: [
        {
          label: 'Level two 1-1',
          children: [
            {
              label: 'Level three 1-1-1',
              children: [
                {
                  label: 'Level four 1-1-1-1',
                },
                {
                  label: 'Level four 1-1-1-2',
                },
              ],
            },
            {
              label: 'Level three 1-1-2',
              children: [
                {
                  label: 'Level four 1-1-2-1',
                },
                {
                  label: 'Level four 1-1-2-2',
                },
              ],
            },
          ],
        },
        {
          label: 'Level two 1-2',
          children: [
            {
              label: 'Level three 1-2-1',
            },
            {
              label: 'Level three 1-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 2',
      children: [
        {
          label: 'Level two 2-1',
          children: [
            {
              label: 'Level three 2-1-1',
            },
            {
              label: 'Level three 2-1-2',
            },
          ],
        },
        {
          label: 'Level two 2-2',
          children: [
            {
              label: 'Level three 2-2-1',
            },
            {
              label: 'Level three 2-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 3',
      children: [
        {
          label: 'Level two 3-1',
          children: [
            {
              label: 'Level three 3-1-1',
            },
            {
              label: 'Level three 3-1-2',
            },
          ],
        },
        {
          label: 'Level two 3-2',
          children: [
            {
              label: 'Level three 3-2-1',
            },
            {
              label: 'Level three 3-2-2',
            },
          ],
        },
      ],
    }
  ]
  build() {
    Column(){
      IBestTree({
        data: this.data!!,
        onNodeClick: (data: IBestTreeData, level: number) => {
          console.log('onNodeClick', JSON.stringify(data), level)
        }
      })
    }
  }
}

可选择

可选择

TIP

selectType 可选值为 single multiple

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      value: '1',
      children: [
        {
          label: 'Level two 1-1',
          value: '1-1'
        }
      ]
    },
    {
      label: 'Level one 2',
      value: '2',
      children: [
        {
          label: 'Level two 2-1',
          value: '2-1'
        },
        {
          label: 'Level two 2-2',
          value: '2-2',
          disabled: true
        }
      ]
    },
    {
      label: 'Level one 3',
      value: '3',
      disabled: true,
      children: [
        {
          label: 'Level two 3-1',
          value: '3-1'
        },
        {
          label: 'Level two 3-2',
          value: '3-2'
        }
      ]
    }
  ]
  build() {
    Column({space: 12}){
      Column(){
        Text("单选")
        IBestTree({
          data: this.data!!,
          selectType: "single",
          selectOnClickNode: true,
          defaultExpandKeys: ['2', '3'],
          onSelectChange: (data: IBestTreeData, level: number) => {
            console.log('onSelectChange', data.label, level)
          }
        })
      }.alignItems(HorizontalAlign.Start)
      Column() {
        Text("多选")
        IBestTree({
          data: this.data!!,
          selectType: "multiple",
          defaultExpandKeys: ['2', '3'],
          onSelectChange: (data: IBestTreeData, level: number, selected?: boolean, indeterminate?: boolean) => {
            console.log('onSelectChange', data.label, level, selected, indeterminate)
          }
        })
      }.alignItems(HorizontalAlign.Start)
    }
  }
}

懒加载节点

懒加载节点

TIP

传入lazyLoad懒加载函数,即可实现节点数据异步显示,有三个参数:
· nodeData:为当前点击的节点数据;
· level:为当前点击的节点层级,默认从0开始;
· cb:为返回函数,参数为当前节点下要展示的节点数据。

由于在点击节点时才进行该层数据的获取,默认情况下 IBestTree 无法预知某个节点是否为叶子节点, 所以会为每个节点添加一个下拉按钮,如果节点没有下层数据,则点击后下拉按钮会消失。 同时,你也可以提前告知 IBestTree 某个节点是否为叶子节点,从而避免在叶子节点前渲染下拉按钮。

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      value: '1'
    },
    {
      label: 'Level one 2',
      value: '2'
    }
  ]
  lazyLoad(nodeData: IBestTreeData, level: number, cb: (arr: IBestTreeData[]) => void){
    console.log('lazyLoad', JSON.stringify(nodeData), level)
    setTimeout(() => {
      if(level == 0){
        cb(nodeData.value == '1' ? [
          {
            label: 'Level two 1-1',
            value: '1-1'
          },
          {
            label: 'Level two 1-2',
            value: '1-2'
          }
        ] : [
          {
            label: 'Level two 2-1',
            value: '2-1'
          },
          {
            label: 'Level two 2-2',
            value: '2-2'
          }
        ])
      }else if(level == 1){
        cb(nodeData.value == '1-1' ? [
          {
            label: 'Level three 1-1-1',
            value: '1-1-1'
          },
          {
            label: 'Level three 1-1-2',
            value: '1-1-2',
            isLeaf: true
          }
        ] : [
          {
            label: 'Level three 2-1-1',
            value: '2-1-1'
          },
          {
            label: 'Level three 2-1-2',
            value: '2-1-2'
          }
        ])
      }else {
        cb([])
      }
    }, 1000)
  }
  build() {
    Column(){
      IBestTree({
        data: this.data!!,
        lazyLoad: (nodeData: IBestTreeData, level: number, cb: (arr: IBestTreeData[]) => void): void => this.lazyLoad(nodeData, level, cb)
      })
    }
  }
}

手风琴

手风琴

TIP

accordion 设置为true,即可开启手风琴效果,即同一层级下只能展开一个节点。

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      children: [
        {
          label: 'Level two 1-1',
          children: [
            {
              label: 'Level three 1-1-1',
              children: [
                {
                  label: 'Level four 1-1-1-1',
                },
                {
                  label: 'Level four 1-1-1-2',
                },
              ],
            },
            {
              label: 'Level three 1-1-2',
              children: [
                {
                  label: 'Level four 1-1-2-1',
                },
                {
                  label: 'Level four 1-1-2-2',
                },
              ],
            },
          ],
        },
        {
          label: 'Level two 1-2',
          children: [
            {
              label: 'Level three 1-2-1',
            },
            {
              label: 'Level three 1-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 2',
      children: [
        {
          label: 'Level two 2-1',
          children: [
            {
              label: 'Level three 2-1-1',
            },
            {
              label: 'Level three 2-1-2',
            },
          ],
        },
        {
          label: 'Level two 2-2',
          children: [
            {
              label: 'Level three 2-2-1',
            },
            {
              label: 'Level three 2-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 3',
      children: [
        {
          label: 'Level two 3-1',
          children: [
            {
              label: 'Level three 3-1-1',
            },
            {
              label: 'Level three 3-1-2',
            },
          ],
        },
        {
          label: 'Level two 3-2',
          children: [
            {
              label: 'Level three 3-2-1',
            },
            {
              label: 'Level three 3-2-2',
            },
          ],
        },
      ],
    }
  ]
  build() {
    Column(){
      IBestTree({
        data: this.data!!,
        accordion: true
      })
    }
  }
}

拖拽

拖拽

TIP

enableDrag 设置为true,即可开启拖拽,拖拽成功后会触发onNodeDrop回调函数:
· dragData为拖拽的节点数据;
· dropData为拖入的节点数据。

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      children: [
        {
          label: 'Level two 1-1',
          children: [
            {
              label: 'Level three 1-1-1'
            },
            {
              label: 'Level three 1-1-2'
            },
          ],
        },
        {
          label: 'Level two 1-2',
          children: [
            {
              label: 'Level three 1-2-1',
            },
            {
              label: 'Level three 1-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 2',
      children: [
        {
          label: 'Level two 2-1',
          children: [
            {
              label: 'Level three 2-1-1',
            },
            {
              label: 'Level three 2-1-2',
            },
          ],
        },
        {
          label: 'Level two 2-2',
          children: [
            {
              label: 'Level three 2-2-1',
            },
            {
              label: 'Level three 2-2-2',
            },
          ],
        },
      ],
    },
    {
      label: 'Level one 3',
      children: [
        {
          label: 'Level two 3-1',
          children: [
            {
              label: 'Level three 3-1-1',
            },
            {
              label: 'Level three 3-1-2',
            },
          ],
        },
        {
          label: 'Level two 3-2',
          children: [
            {
              label: 'Level three 3-2-1',
            },
            {
              label: 'Level three 3-2-2',
            },
          ],
        },
      ],
    }
  ]
  build() {
    Column(){
      IBestTree({
        data: this.data!!,
        enableDrag: true,
        onNodeDrop: (dragData: IBestTreeNodeData, dropData: IBestTreeNodeData) => {
          IBestDialogUtil.open({
            message: `拖拽节点为${dragData.label}, 拖入节点为${dropData.label}`
          })
        }
      })
    }
  }
}

自定义节点

拖拽

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      value: 1,
      children: [
        {
          label: 'Level two 1-1',
          value: 4,
          children: [
            {
              label: 'Level three 1-1-1',
              value: 9,
            },
            {
              label: 'Level three 1-1-2',
              value: 10,
            }
          ]
        }
      ]
    },
    {
      label: 'Level one 2',
      value: 2,
      children: [
        {
          label: 'Level two 2-1',
          value: 5
        },
        {
          label: 'Level two 2-2',
          value: 6
        }
      ]
    },
    {
      label: 'Level one 3',
      value: 3,
      children: [
        {
          label: 'Level two 3-1',
          value: 7
        },
        {
          label: 'Level two 3-2',
          value: 8
        }
      ]
    }
  ]
  private nodeId: number = 1000
  @Builder customNodeBuilder(node: IBestTreeNodeData){
    Row(){
      Text(node.label).fontSize(14)
      Row({space: 10}){
        Text("添加").fontColor("#1989fa").onClick(() => {
          node.append({
            label: "添加节点",
            value: this.nodeId++  // 此处为模拟
          })
        })
        Text("删除").fontColor("#ed4040").onClick(() => {
          node.remove()
        })
      }
    }
    .layoutWeight(1)
    .justifyContent(FlexAlign.SpaceBetween)
  }
  build() {
    Column(){
      IBestTree({
        data: this.data!!,
        defaultExpandAll: true,
        nodeBuilder: (node: IBestTreeNodeData): void => this.customNodeBuilder(node)
      })
    }
  }
}

组件方法

拖拽

TIP

组件方法仅在selectType不为空时有效。

点我查看代码
ts
@Entry
@ComponentV2
struct DemoPage {
  @Local data: IBestTreeData[] = [
    {
      label: 'Level one 1',
      value: 1,
      children: [
        {
          label: 'Level two 1-1',
          value: 4,
          children: [
            {
              label: 'Level three 1-1-1',
              value: 9,
            },
            {
              label: 'Level three 1-1-2',
              value: 10,
            }
          ]
        }
      ]
    },
    {
      label: 'Level one 2',
      value: 2,
      children: [
        {
          label: 'Level two 2-1',
          value: 5
        },
        {
          label: 'Level two 2-2',
          value: 6
        }
      ]
    },
    {
      label: 'Level one 3',
      value: 3,
      children: [
        {
          label: 'Level two 3-1',
          value: 7
        },
        {
          label: 'Level two 3-2',
          value: 8
        }
      ]
    }
  ]
  private controller: IBestTreeController = new IBestTreeController()
  build() {
    Column({space: 12}){
      IBestTree({
        data: this.data!!,
        selectType: "multiple",
        defaultExpandAll: true,
        controller: this.controller
      })
      Row({space: 12}){
        IBestButton({
          type: "primary",
          text: "设置选中节点",
          onBtnClick: () => {
            this.controller.setCheckedNodes([5, 6, 9])
          }
        })
        IBestButton({
          type: "primary",
          text: "获取选中节点",
          onBtnClick: () => {
            const nodes = this.controller.getCheckedNodes()
            IBestDialogUtil.open({
              message: `选中节点为${nodes.map(e => e.label).join("、")}`
            })
          }
        })
        IBestButton({
          type: "primary",
          text: "重置",
          onBtnClick: () => {
            this.controller.reset()
          }
        })
      }
    }
  }
}

API

@Props

参数说明类型默认值
data节点数据,双向绑定IBestTreeData[][]
defaultExpandAll默认展开所有节点booleanfalse
defaultExpandKeys默认展开的节点value值,需节点数据中传入value(string | number)[][]
selectType可选择类型,可选值 singlemultiplestring''
arrowIcon箭头图标ResourceStrplay
arrowIconSize箭头图标大小string | number12
accordion是否开启手风琴模式booleanfalse
enableDrag是否开启拖拽功能booleanfalse
expandOnClickNode是否在点击节点的时候展开或者收起节点,如果为false,则只有点击箭头图标的时候才会展开或者收缩节点booleantrue
selectOnClickNode是否在点击节点的时候选中节点,如果为false,则只有点击单选/复选框的时候才会选中节点booleanfalse
lazyLoad节点懒加载函数,data为当前点击的节点数据,level为当前点击的节点层级,默认从0开始,cb为返回函数,参数为当前节点下要展示的节点数据(data: IBestTreeData, level: number, cb: (arr: IBestTreeData[]) => void) => void-
controller组件控制器IBestTreeController-

Events

事件名说明事件类型
onNodeClick节点点击回调,data为当前点击的节点数据,level为当前点击的节点层级(data: IBestTreeData, level: number) => void
onSelectChange选择状态改变回调,data 为当前选中的节点数据,level 为节点层级,当selectTypemultiple时,selected为当前节点选中状态,indeterminate为当前节点是否部分选中(data: IBestTreeData, level: number, selected?: boolean, indeterminate?: boolean) => void
onNodeDrop拖拽回调,dragData为拖拽的节点数据,dropData为拖入的节点数据(dragNode: IBestTreeNodeData, dropNode: IBestTreeNodeData) => void

插槽

插槽名说明类型
nodeBuilder自定义节点插槽(node: IBestTreeNodeData) => void

IBestTreeData 数据结构

参数说明类型默认值
label节点名称ResourceStr''
value节点值string | number''
isLeaf是否是叶子节点,仅在传入了lazyLoad函数时有效booleanfalse
disabled当前节点是否禁用,仅selectType不为空时生效booleanfalse
children子节点数据IBestTreeData[][]

IBestTreeNodeData extends IBestTreeData 数据结构

参数说明类型默认值
append在当前节点下添加数据(data: IBestTreeData) => void-
remove移除当前节点() => void-

IBestTreeController 实例

方法名说明参数类型返回值
setCheckedNodes设置选中节点,仅selectType不为空时可用keys: IBestStringNumber[]void
getCheckedNodes获取选中节点,仅selectType不为空时可用-IBestTreeData[]
reset重置选中,仅selectType不为空时可用-void

主题定制

l 组件提供了下列颜色变量,可用于自定义深色/浅色模式样式,使用方法请参考 颜色模式 章节,如需要其它颜色变量可提 issue

名称描述默认值
ibest_tree_background背景色#fff
ibest_tree_active_background激活背景色#f2f3f5