Tree 树形控件
介绍
用清晰的层级结构展示信息,可展开或折叠。
TIP
阅读该组件文档前请确保**已认真阅读快速上手章节的每一个字**。
引入
ts
import { IBestTree, IBestTreeController, IBestTreeData, IBestTreeNodeData } from "@ibestservices/ibest-ui";代码演示
基础用法

点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $data,
onNodeClick: (data: IBestTreeData, level: number) => {
console.log('onNodeClick', JSON.stringify(data), level)
}
})
}
}
}可选择

TIP
selectType 可选值为 single multiple。
点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $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: $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
@Component
struct DemoPage {
@State 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: $data,
lazyLoad: (nodeData: IBestTreeData, level: number, cb: (arr: IBestTreeData[]) => void): void => this.lazyLoad(nodeData, level, cb)
})
}
}
}手风琴

TIP
accordion 设置为true,即可开启手风琴效果,即同一层级下只能展开一个节点。
点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $data,
accordion: true
})
}
}
}拖拽

TIP
enableDrag 设置为true,即可开启拖拽,拖拽成功后会触发onNodeDrop回调函数:
· dragData为拖拽的节点数据;
· dropData为拖入的节点数据。
点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $data,
enableDrag: true,
onNodeDrop: (dragData: IBestTreeNodeData, dropData: IBestTreeNodeData) => {
IBestDialogUtil.open({
message: `拖拽节点为${dragData.label}, 拖入节点为${dropData.label}`
})
}
})
}
}
}自定义节点

点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $data,
defaultExpandAll: true,
nodeBuilder: (node: IBestTreeNodeData): void => this.customNodeBuilder(node)
})
}
}
}组件方法

TIP
组件方法仅在selectType不为空时有效。
点我查看代码
ts
@Entry
@Component
struct DemoPage {
@State 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: $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 | 默认展开所有节点 | boolean | false |
| defaultExpandKeys | 默认展开的节点value值,需节点数据中传入value | (string | number)[] | [] |
| selectType | 可选择类型,可选值 single、multiple | string | '' |
| arrowIcon | 箭头图标 | ResourceStr | play |
| arrowIconSize | 箭头图标大小 | string | number | 12 |
| accordion | 是否开启手风琴模式 | boolean | false |
| enableDrag | 是否开启拖拽功能 | boolean | false |
| expandOnClickNode | 是否在点击节点的时候展开或者收起节点,如果为false,则只有点击箭头图标的时候才会展开或者收缩节点 | boolean | true |
| selectOnClickNode | 是否在点击节点的时候选中节点,如果为false,则只有点击单选/复选框的时候才会选中节点 | boolean | false |
| 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 为节点层级,当selectType为multiple时,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函数时有效 | boolean | false |
| disabled | 当前节点是否禁用,仅selectType不为空时生效 | boolean | false |
| 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 |