更新记录
1.0.1(2025-11-19)
下载此版本
增加截图,完善多选
1.0.0(2025-11-19)
下载此版本
市场上实在找不到我想要的,树形选择控件,即支持回显、虚拟列表海量数据支持、懒加载、等等。用AI写了一个组件,基本上element-plus Tree V2 虚拟化树形控件有的功能这个组件都有。
平台兼容性
uni-app(3.6.14)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
√ |
√ |
√ |
- |
√ |
√ |
√ |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
快应用-华为 |
快应用-联盟 |
| √ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
uni-app x(3.7.6)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
- |
- |
- |
- |
zzh-virtual-treeselect
介绍
zzh-virtual-treeselect 是一个基于 uni-app 的虚拟树形选择组件,包含两个核心组件:
- zzh-virtual-picker - 底层核心虚拟滚动树形选择器
- zzh-virtual-treeselect - 带选择框的高级包装组件
该组件集成了虚拟滚动技术,能够高效渲染大量树形数据,同时提供了丰富的交互功能和良好的用户体验。
特点
zzh-virtual-picker (核心选择器)
- 🚀 虚拟滚动:支持大量数据渲染,性能优异
- 🔄 双向绑定:支持 v-model 双向数据绑定
- 🔘 多种选择模式:支持单选和多选
- 📂 树形结构:支持无限层级树形数据展示
- 🎯 节点状态:支持禁用、展开/折叠状态
- ⚡ 懒加载:支持异步加载子节点数据
- 🔍 搜索过滤:内置搜索功能,支持数据过滤
- 🎨 插槽自定义:支持自定义节点渲染
- 🌿 叶子节点限制:可限制只能选择叶子节点
- 📱 跨平台:支持 H5、App、小程序等多端运行
zzh-virtual-treeselect (选择框包装组件)
- 🎨 友好界面:提供类似 Select 的选择框界面
- 🏷️ 标签显示:多选时以标签形式展示选中项
- 🔍 缩略显示:标签过多时自动缩略显示 (+N)
- 🧹 一键清除:支持清除已选项
- 🚫 禁用状态:支持禁用状态
- 🔗 无缝集成:基于 zzh-virtual-picker 构建
- 🔄 双向绑定:支持 v-model 双向数据绑定
- 📱 跨平台:支持 H5、App、小程序等多端运行
zzh-virtual-picker Props
| 参数 |
类型 |
默认值 |
说明 |
| value |
[Array, String, Number] |
[] |
绑定值,多选时为数组 |
| data |
Array |
[] |
树形数据源 |
| show |
Boolean |
false |
是否显示弹框 |
| title |
String |
'请选择' |
弹框标题 |
| confirmText |
String |
'确认' |
确认按钮文字 |
| cancelText |
String |
'取消' |
取消按钮文字 |
| maskClick |
Boolean |
true |
是否可通过点击遮罩关闭 |
| showSearch |
Boolean |
false |
是否显示搜索框 |
| searchPlaceholder |
String |
'请输入搜索关键字' |
搜索框占位符 |
| bodyHeight |
String |
'300px' |
弹框主体高度 |
| props |
Object |
{id: 'id', label: 'label', children: 'children', disabled: 'disabled', isLeaf: 'isLeaf'} |
节点字段映射配置 |
| checkable |
Boolean |
true |
节点是否可选择 |
| checkType |
String |
'checkbox' |
选择类型:'checkbox'(多选)或 'radio'(单选) |
| checkLeafOnly |
Boolean |
false |
是否只能选择叶子节点 |
| lazy |
Boolean |
false |
是否启用懒加载 |
| load |
Function |
null |
懒加载方法,返回 Promise |
| itemHeight |
Number |
50 |
节点高度(px) |
| indentSize |
Number |
20 |
节点缩进大小(px) |
zzh-virtual-picker Slots
| 名称 |
说明 |
| trigger |
触发器插槽 |
| node |
节点内容插槽,参数:{node, level} |
zzh-virtual-picker Events
| 事件名 |
说明 |
参数 |
| change |
值改变时触发 |
选中的值 |
| confirm |
点击确认时触发 |
选中的值 |
| cancel |
点击取消时触发 |
- |
| check-change |
节点选中状态改变时触发 |
(selectedNodes, node, isChecked) |
| radio-change |
单选节点改变时触发 |
(selectedKey, selectedNode) |
zzh-virtual-treeselect Props
| 参数 |
类型 |
默认值 |
说明 |
| value |
[Array, String, Number] |
null |
绑定值 |
| data |
Array |
[] |
树形数据源 |
| multiple |
Boolean |
false |
是否多选 |
| placeholder |
String |
'请选择' |
占位符文字 |
| clearable |
Boolean |
false |
是否可清除 |
| disabled |
Boolean |
false |
是否禁用 |
| title |
String |
'请选择' |
弹框标题 |
| confirmText |
String |
'确认' |
确认按钮文字 |
| cancelText |
String |
'取消' |
取消按钮文字 |
| maskClick |
Boolean |
true |
是否可通过点击遮罩关闭 |
| showSearch |
Boolean |
false |
是否显示搜索框 |
| searchPlaceholder |
String |
'请输入搜索关键字' |
搜索框占位符 |
| bodyHeight |
String |
'300px' |
弹框主体高度 |
| props |
Object |
{id: 'id', label: 'label', children: 'children', disabled: 'disabled', isLeaf: 'isLeaf'} |
节点字段映射配置 |
| checkable |
Boolean |
true |
节点是否可选择 |
| checkLeafOnly |
Boolean |
false |
是否只能选择叶子节点 |
| lazy |
Boolean |
false |
是否启用懒加载 |
| load |
Function |
null |
懒加载方法,返回 Promise |
| itemHeight |
Number |
50 |
节点高度(px) |
| indentSize |
Number |
20 |
节点缩进大小(px) |
| maxTagCount |
Number |
3 |
最大显示标签数 |
zzh-virtual-treeselect Slots
| 名称 |
说明 |
| trigger |
触发器插槽(覆盖默认选择框) |
| node |
节点内容插槽,参数:{node, level} |
zzh-virtual-treeselect Events
| 事件名 |
说明 |
参数 |
| change |
值改变时触发 |
选中的值 |
| confirm |
点击确认时触发 |
选中的值 |
| cancel |
点击取消时触发 |
- |
| clear |
点击清除时触发 |
- |
使用示例
1. 基础用法 (zzh-virtual-treeselect)
<template>
<view>
<!-- 基础单选 -->
<zzh-virtual-treeselect
v-model="selectedValue"
:data="treeData"
placeholder="请选择"
/>
<!-- 多选 -->
<zzh-virtual-treeselect
v-model="selectedValues"
:data="treeData"
multiple
placeholder="请选择多项"
/>
<!-- 可清除的单选 -->
<zzh-virtual-treeselect
v-model="selectedValue2"
:data="treeData"
placeholder="请选择"
clearable
/>
<!-- 多选带标签限制 -->
<zzh-virtual-treeselect
v-model="selectedValues2"
:data="treeData"
multiple
placeholder="请选择(最多显示2个标签)"
:max-tag-count="2"
clearable
/>
<!-- 禁用状态 -->
<zzh-virtual-treeselect
v-model="selectedValue3"
:data="treeData"
placeholder="禁用状态"
disabled
/>
</view>
</template>
<script>
import ZzhVirtualTreeselect from '@/uni_modules/zzh-virtual-treeselect/components/zzh-virtual-treeselect/zzh-virtual-treeselect.vue'
export default {
components: {
ZzhVirtualTreeselect
},
data() {
return {
selectedValue: null,
selectedValues: [],
selectedValue2: null,
selectedValues2: [],
selectedValue3: null,
treeData: [
{
id: 1,
label: '一级节点1',
children: [
{
id: 2,
label: '二级节点1-1',
children: [
{ id: 3, label: '三级节点1-1-1' },
{ id: 4, label: '三级节点1-1-2' }
]
},
{ id: 5, label: '二级节点1-2' }
]
},
{
id: 6,
label: '一级节点2',
children: [
{ id: 7, label: '二级节点2-1' },
{ id: 8, label: '二级节点2-2' }
]
}
]
}
}
}
</script>
2. 高级用法 (zzh-virtual-picker)
<template>
<view>
<!-- 自定义触发器 -->
<zzh-virtual-picker
v-model="selectedValues"
:data="treeData"
:show.sync="showPicker"
title="请选择节点"
check-type="checkbox"
:show-search="true"
search-placeholder="搜索节点"
:lazy="true"
:load="loadNode"
>
<!-- 自定义触发器 -->
<template #trigger>
<button @click="showPicker = true">选择节点</button>
</template>
<!-- 自定义节点内容 -->
<template #node="{ node, level }">
<text style="color: #007AFF;">{{ node.label }} (层级: {{ level }})</text>
</template>
</zzh-virtual-picker>
<!-- 显示选中结果 -->
<view style="margin-top: 20px;">
<text>选中节点: {{ selectedValues }}</text>
</view>
</view>
</template>
<script>
import ZzhVirtualPicker from '@/uni_modules/zzh-virtual-treeselect/components/zzh-virtual-picker/zzh-virtual-picker.vue'
export default {
components: {
ZzhVirtualPicker
},
data() {
return {
showPicker: false,
selectedValues: [],
treeData: [
{
id: 1,
label: '根节点1',
isLeaf: false
},
{
id: 2,
label: '根节点2',
isLeaf: false
}
]
}
},
methods: {
// 懒加载子节点
loadNode(node) {
return new Promise(resolve => {
setTimeout(() => {
const children = [
{ id: `${node.id}-1`, label: `${node.label}-子节点1`, isLeaf: true },
{ id: `${node.id}-2`, label: `${node.label}-子节点2`, isLeaf: true }
]
resolve(children)
}, 1000)
})
}
}
}
</script>
3. 仅叶子节点可选
<template>
<view>
<zzh-virtual-treeselect
v-model="selectedValue"
:data="treeData"
placeholder="只能选择叶子节点"
:check-leaf-only="true"
/>
</view>
</template>
<script>
import ZzhVirtualTreeselect from '@/uni_modules/zzh-virtual-treeselect/components/zzh-virtual-treeselect/zzh-virtual-treeselect.vue'
export default {
components: {
ZzhVirtualTreeselect
},
data() {
return {
selectedValue: null,
treeData: [
{
id: 1,
label: '父节点1',
children: [
{ id: 2, label: '叶子节点1-1' },
{ id: 3, label: '叶子节点1-2' }
]
}
]
}
}
}
</script>
注意事项
- 性能优化:虚拟滚动适用于大量数据场景,小量数据可考虑使用普通树形组件
- 数据结构:确保数据结构符合要求,id 字段唯一
- 懒加载:使用懒加载时,需要正确实现 load 方法并返回 Promise
- 跨平台兼容:组件已适配 H5、App、小程序等平台
- Vue 版本:组件兼容 Vue 2 和 Vue 3,使用 model 选项确保 v-model 正常工作