vue实现treeview
Vue实现TreeView的方法
使用递归组件实现基础TreeView
递归组件是Vue中实现树形结构的常见方式。通过组件调用自身来渲染嵌套的子节点。
<template>
<ul>
<li v-for="node in treeData" :key="node.id">
{{ node.label }}
<tree-node v-if="node.children" :treeData="node.children"/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
treeData: Array
}
}
</script>
使用时传入树形数据:
data() {
return {
treeData: [
{
id: 1,
label: '节点1',
children: [
{ id: 2, label: '子节点1' },
{ id: 3, label: '子节点2' }
]
}
]
}
}
添加展开/折叠功能
通过添加isOpen状态控制节点的展开与折叠:

<template>
<ul>
<li v-for="node in treeData" :key="node.id">
<span @click="toggle(node)">{{ node.isOpen ? '-' : '+' }}</span>
{{ node.label }}
<tree-node
v-if="node.children && node.isOpen"
:treeData="node.children"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
treeData: Array
},
methods: {
toggle(node) {
this.$set(node, 'isOpen', !node.isOpen)
}
}
}
</script>
使用第三方库
对于更复杂的需求,可以考虑以下Vue树形组件库:
vue-tree-halation:功能丰富的树形组件vue-jstree:基于jstree的Vue实现element-ui的el-tree:Element UI提供的树形组件
安装Element UI并使用el-tree:

npm install element-ui
<template>
<el-tree
:data="treeData"
:props="defaultProps"
@node-click="handleNodeClick"
></el-tree>
</template>
<script>
export default {
data() {
return {
treeData: [{
label: '一级节点',
children: [{
label: '二级节点'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
}
},
methods: {
handleNodeClick(data) {
console.log(data)
}
}
}
</script>
实现拖拽功能
使用vuedraggable实现树形结构的拖拽排序:
npm install vuedraggable
<template>
<div>
<vuedraggable
v-for="node in treeData"
:key="node.id"
:list="node.children"
group="nodes"
>
<div>
{{ node.label }}
<tree-node :treeData="node.children"/>
</div>
</vuedraggable>
</div>
</template>
<script>
import vuedraggable from 'vuedraggable'
export default {
components: { vuedraggable },
props: {
treeData: Array
}
}
</script>
性能优化建议
对于大型树形结构,考虑使用虚拟滚动优化性能。vue-virtual-scroll-list等库可以帮助实现:
npm install vue-virtual-scroll-list
<template>
<virtual-list
:size="30"
:remain="10"
:data-key="'id'"
:data-sources="flattenedTreeData"
>
<template #default="{ source }">
<div :style="{ paddingLeft: source.level * 20 + 'px' }">
{{ source.label }}
</div>
</template>
</virtual-list>
</template>
<script>
import VirtualList from 'vue-virtual-scroll-list'
export default {
components: { VirtualList },
computed: {
flattenedTreeData() {
// 将树形数据展平并添加层级信息
return this.flattenTree(this.treeData)
}
},
methods: {
flattenTree(nodes, level = 0) {
let result = []
nodes.forEach(node => {
result.push({ ...node, level })
if (node.children) {
result = result.concat(this.flattenTree(node.children, level + 1))
}
})
return result
}
}
}
</script>






