更新记录
1.0.0(2026-08-06)
下载此版本
新增
- 基于 uni-app x Composition API + UTS 开发的跨平台无限级树形组件
- 递归节点自渲染,支持任意层级树形数据,零性能损耗的扁平索引
- 展开/折叠节点,折叠时整棵子树不渲染(v-if),大幅减少 DOM 节点
- 手风琴模式,同一层级仅允许一个节点展开
- Checkbox 多选模式,支持父子联动(级联选中/半选)或严格不联动
- 节点点击选中高亮,支持受控(selectedKey)和非受控两种模式
- 异步懒加载(loadData),带加载中状态提示,自动防重复加载
- 纯 CSS 箭头图标(border 三角 + transform rotate),无图片/字体图标依赖
- 跨平台兼容:App(Android / iOS / Harmony)、Web、微信小程序
平台兼容性
uni-app(4.87)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| - |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| √ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
uni-app x(4.87)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| √ |
√ |
√ |
√ |
√ |
√ |
jack-tree-ui 无限级树形组件
兼容各端(Android / iOS / Harmony、Web、微信小程序)的无限级树形组件。基于 provide/inject 通信,递归节点自渲染,折叠时子树完全挂载移除(v-if),大规模数据场景性能可控。
特性
- 无限递归:任意层级嵌套,节点组件自引用
- 展开/折叠:v-if 控制子树挂载,折叠状态下零 DOM 开销
- 手风琴模式:
accordion 开启后同级节点仅一个展开
- 多选复选框:支持父子联动(级联选中 + 半选态)或严格不联动
- 节点选中:点击高亮,受控 / 非受控均可
- 异步懒加载:
loadData 回调加载子节点,内置 loading 防重复
- 扁平索引:Map 存储全量节点,O(1) 查找任意节点
- 零外部依赖:纯 CSS 箭头图标,不依赖 uni-icons 等三方组件
- 跨平台一致:App(Android / iOS / Harmony)、Web、微信小程序
属性 Props
| 属性名 |
类型 |
默认值 |
说明 |
| data |
TreeData[] |
[] |
树形数据源,根节点数组 |
| accordion |
boolean |
false |
是否启用手风琴模式 |
| showCheckbox |
boolean |
false |
是否显示多选框 |
| selectable |
boolean |
true |
节点是否可点击选中 |
| expandAll |
boolean |
false |
是否默认展开全部节点 |
| expandedKeys |
string[] |
[] |
指定默认展开的节点 key(受控) |
| selectedKey |
string |
'' |
当前选中节点 key(受控) |
| checkedKeys |
string[] |
[] |
当前勾选节点 key 列表(受控) |
| indentWidth |
string |
'36rpx' |
每级缩进宽度 |
| itemHeight |
string |
'80rpx' |
每行节点行高 |
| loadData |
(node: TreeNode) => Promise<TreeNode[]> |
null |
异步加载子节点回调 |
| checkStrictly |
boolean |
false |
父子节点选中状态是否独立 |
| onlyLeafCheckable |
boolean |
false |
是否仅叶子节点可勾选 |
| nodeKey |
string |
'id' |
节点唯一标识字段名 |
| childrenField |
string |
'children' |
子节点列表字段名 |
| labelField |
string |
'label' |
显示文本字段名 |
| disabledField |
string |
'disabled' |
禁用状态字段名 |
| lazyField |
string |
'lazy' |
懒加载标记字段名 |
事件 Events
| 事件名 |
参数 |
说明 |
| node-click |
{ node: TreeNode, expanded: boolean } |
点击节点行 |
| node-expand |
{ node: TreeNode, expanded: boolean } |
展开/折叠状态变化 |
| node-select |
{ node: TreeNode, selectedKey: string } |
选中节点变化 |
| node-check |
{ checkedKeys: string[], checkedNodes: TreeNode[], node: TreeNode, checked: boolean } |
勾选状态变化 |
| load-data-success |
{ parentNode: TreeNode, children: TreeNode[] } |
懒加载成功回调 |
| load-data-error |
{ parentNode: TreeNode, error: Error } |
懒加载失败回调 |
方法 Expose
通过 ref 获取组件实例后调用。
| 方法 |
参数 |
返回值 |
说明 |
| expandAll() |
— |
void |
展开全部节点 |
| collapseAll() |
— |
void |
折叠全部节点 |
| getCheckedKeys() |
— |
string[] |
获取所有勾选节点 key |
| getCheckedNodes() |
— |
TreeNode[] |
获取所有勾选节点数据 |
| getSelectedNode() |
— |
TreeNode \| null |
获取当前选中节点 |
| getExpandedKeys() |
— |
string[] |
获取所有展开节点 key |
| setExpanded(keys) |
string[] |
void |
设置展开节点列表 |
| setChecked(keys) |
string[] |
void |
设置勾选节点列表 |
| setSelected(key) |
string |
void |
设置选中节点 |
| getNodeByKey(key) |
string |
TreeNode \| null |
根据 key 查找节点 |
使用示例
基础用法
<template>
<jack-tree-ui
:data="treeData"
@node-click="onNodeClick"
/>
</template>
<script lang="uts" setup>
import { ref } from 'vue'
const treeData = ref([
{
id: '1',
label: '一级节点',
children: [
{ id: '1-1', label: '二级节点-1' },
{ id: '1-2', label: '二级节点-2', children: [
{ id: '1-2-1', label: '三级节点' }
]}
]
}
])
function onNodeClick(e: { node: any, expanded: boolean }): void {
console.log('clicked:', e.node.label)
}
</script>
多选模式
<template>
<jack-tree-ui
ref="treeRef"
:data="treeData"
:showCheckbox="true"
@node-check="onNodeCheck"
/>
</template>
<script lang="uts" setup>
import { ref } from 'vue'
const treeRef = ref(null)
function onNodeCheck(e: { checkedKeys: string[], checkedNodes: any[], node: any, checked: boolean }): void {
console.log('勾选列表:', e.checkedKeys)
}
function getSelected(): void {
const keys = treeRef.value?.getCheckedKeys()
console.log('当前勾选:', keys)
}
</script>
手风琴 + 懒加载
<template>
<jack-tree-ui
:data="treeData"
:accordion="true"
:loadData="loadChildren"
@load-data-success="onLoadSuccess"
/>
</template>
<script lang="uts" setup>
import { ref } from 'vue'
const treeData = ref([
{ id: '1', label: '异步节点', lazy: true, children: [] }
])
function loadChildren(node: any): Promise<any[]> {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ id: node.id + '-1', label: '加载的子节点-1' },
{ id: node.id + '-2', label: '加载的子节点-2' }
])
}, 500)
})
}
function onLoadSuccess(e: { parentNode: any, children: any[] }): void {
console.log('加载完成:', e.children.length, '个子节点')
}
</script>
数据结构 TreeNode
type TreeNode = {
id: string // 唯一标识(字段名由 nodeKey 指定)
label: string // 显示文本(字段名由 labelField 指定)
children: TreeNode[] // 子节点列表(字段名由 childrenField 指定)
disabled: boolean // 是否禁用
lazy: boolean // 是否懒加载
checked: boolean // 勾选状态(组件内部管理)
indeterminate: boolean // 半选状态(组件内部管理)
[key: string]: any // 允许扩展自定义字段
}
平台兼容
| 平台 |
版本要求 |
状态 |
| Android (Vapor) |
HBuilderX 3.9+ |
支持 |
| iOS (Vapor) |
HBuilderX 4.11+ |
支持 |
| Harmony (Vapor) |
HBuilderX 4.61+ |
支持 |
| Web (Chrome) |
HBuilderX 4.0+ |
支持 |
| Web (Safari) |
HBuilderX 4.0+ |
支持 |
| 微信小程序 |
HBuilderX 4.41+ |
支持 |
注意事项
- Vapor 模式限制:CSS
transition 不支持,展开/折叠为瞬时切换(非缺陷,框架限制)
- 选择器限制:仅支持 class 选择器,必须为每个需要样式的元素指定 class
- 文字样式:必须直接写在
<text> 组件上,不支持从父级继承
- 默认布局:flex 布局,
flex-direction 默认 column,box-sizing 默认 border-box
- 大数据场景:折叠子树不渲染,实测万级节点展开数百行时性能良好;如需全展开超大数据集,建议搭配虚拟列表