vue实现树形框
Vue 树形组件实现方法
使用递归组件实现基础树形结构
递归组件是 Vue 中实现树形结构的常见方式。通过组件调用自身的方式展示嵌套数据。
<template>
<ul>
<li v-for="item in treeData" :key="item.id">
{{ item.label }}
<tree-node v-if="item.children" :treeData="item.children"></tree-node>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
treeData: {
type: Array,
required: true
}
}
}
</script>
数据格式示例:
[
{
id: 1,
label: '节点1',
children: [
{
id: 2,
label: '子节点1'
}
]
}
]
添加展开/折叠功能
通过控制节点的 visible 属性实现展开折叠效果。
<template>
<ul>
<li v-for="item in treeData" :key="item.id">
<span @click="toggle(item)">{{ item.expanded ? '-' : '+' }}</span>
{{ item.label }}
<tree-node
v-if="item.children && item.expanded"
:treeData="item.children"
></tree-node>
</li>
</ul>
</template>
<script>
export default {
methods: {
toggle(item) {
this.$set(item, 'expanded', !item.expanded)
}
}
}
</script>
添加复选框功能
通过维护选中状态实现多级复选框联动。

<template>
<ul>
<li v-for="item in treeData" :key="item.id">
<input
type="checkbox"
v-model="item.checked"
@change="handleCheckChange(item)"
>
{{ item.label }}
<tree-node
v-if="item.children && item.expanded"
:treeData="item.children"
@check-change="onChildCheckChange"
></tree-node>
</li>
</ul>
</template>
<script>
export default {
methods: {
handleCheckChange(item) {
this.$emit('check-change', item)
},
onChildCheckChange(child) {
const allChecked = this.treeData.every(item => item.checked)
this.$emit('check-change', { ...this.treeData[0], checked: allChecked })
}
}
}
</script>
使用第三方库
对于复杂需求,可以考虑以下成熟的开源组件:
- Element UI 的 Tree 组件
- Vue Tree Select
- Vue Draggable Tree
安装 Element UI Tree 示例:
npm install element-ui
使用示例:

<template>
<el-tree
:data="treeData"
show-checkbox
node-key="id"
:props="defaultProps"
></el-tree>
</template>
<script>
import { Tree } from 'element-ui'
export default {
components: {
'el-tree': Tree
},
data() {
return {
treeData: [/* 数据 */],
defaultProps: {
children: 'children',
label: 'label'
}
}
}
}
</script>
性能优化建议
大数据量情况下考虑虚拟滚动技术,只渲染可视区域内的节点。可以使用 vue-virtual-scroll-tree 等专门优化的库。
实现懒加载功能,当节点展开时才加载子节点数据:
async toggle(item) {
if (!item.childrenLoaded && item.hasChildren) {
item.children = await loadChildren(item.id)
item.childrenLoaded = true
}
item.expanded = !item.expanded
}
自定义节点内容
通过作用域插槽实现高度自定义的节点渲染:
<el-tree :data="data">
<template #default="{ node, data }">
<span>{{ node.label }}</span>
<span v-if="data.tag" class="tag">{{ data.tag }}</span>
</template>
</el-tree>






