vue实现树型组件
vue实现树型组件
数据结构和递归组件
树型组件通常需要递归渲染,数据格式一般为嵌套结构。常见的数据结构如下:
treeData: [
{
id: 1,
label: '节点1',
children: [
{
id: 2,
label: '节点1.1',
children: []
}
]
}
]
递归组件通过组件自身调用自身实现:
<template>
<ul>
<li v-for="item in data" :key="item.id">
{{ item.label }}
<tree-node v-if="item.children" :data="item.children"/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: ['data']
}
</script>
展开/折叠功能
通过添加isOpen状态控制子节点显示:

<template>
<ul>
<li v-for="item in data" :key="item.id">
<span @click="toggle(item)">{{ item.isOpen ? '-' : '+' }}</span>
{{ item.label }}
<tree-node
v-if="item.children && item.isOpen"
:data="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
methods: {
toggle(item) {
this.$set(item, 'isOpen', !item.isOpen)
}
}
}
</script>
复选框功能
添加全选/半选状态需要计算选中状态:
<template>
<ul>
<li v-for="item in data" :key="item.id">
<input
type="checkbox"
v-model="item.checked"
@change="handleCheckChange(item)"
>
{{ item.label }}
<tree-node
v-if="item.children"
:data="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
methods: {
handleCheckChange(item) {
// 向下同步选中状态
if (item.children) {
item.children.forEach(child => {
child.checked = item.checked
})
}
// 向上同步选中状态
this.updateParentChecked(item)
},
updateParentChecked(item) {
// 实现父节点状态更新逻辑
}
}
}
</script>
动态加载
实现懒加载需要添加加载方法:

<template>
<ul>
<li v-for="item in data" :key="item.id">
<span @click="loadChildren(item)">加载</span>
{{ item.label }}
<tree-node
v-if="item.children"
:data="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
methods: {
async loadChildren(item) {
if (!item.children) {
const res = await api.getChildren(item.id)
this.$set(item, 'children', res.data)
}
}
}
}
</script>
样式优化
添加缩进和图标增强视觉效果:
.tree-node {
padding-left: 20px;
position: relative;
}
.tree-node:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 16px;
height: 100%;
border-left: 1px solid #ddd;
}
性能优化
对于大型树结构,建议使用虚拟滚动:
<template>
<virtual-list :size="40" :remain="20">
<tree-node v-for="item in visibleData" :data="item"/>
</virtual-list>
</template>






