vue树形展示实现
Vue 树形展示实现方法
使用递归组件实现树形结构
递归组件是 Vue 中实现树形结构的常见方式。通过组件调用自身,可以轻松处理嵌套数据。
<template>
<ul>
<li v-for="item in treeData" :key="item.id">
{{ item.name }}
<tree-node v-if="item.children" :treeData="item.children"></tree-node>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
treeData: Array
}
}
</script>
数据格式通常为:
[
{
id: 1,
name: '父节点',
children: [
{
id: 2,
name: '子节点'
}
]
}
]
使用第三方组件库
Element UI、Ant Design Vue 等流行 UI 库都提供了现成的树形组件。
Element UI 示例:
<el-tree
:data="treeData"
:props="defaultProps"
@node-click="handleNodeClick">
</el-tree>
<script>
export default {
data() {
return {
treeData: [/* 树形数据 */],
defaultProps: {
children: 'children',
label: 'name'
}
}
}
}
</script>
实现展开/折叠功能
为树形节点添加展开/折叠功能需要维护一个状态:
<template>
<div>
<div @click="toggle">
{{ node.name }}
<span v-if="hasChildren">{{ isOpen ? '-' : '+' }}</span>
</div>
<div v-show="isOpen" v-if="hasChildren">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child">
</tree-node>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false
}
},
computed: {
hasChildren() {
return this.node.children && this.node.children.length
}
},
methods: {
toggle() {
this.isOpen = !this.isOpen
}
}
}
</script>
添加复选框功能
实现带复选框的树形组件需要处理选中状态:
<template>
<div>
<input
type="checkbox"
v-model="node.checked"
@change="handleCheckChange">
<span>{{ node.name }}</span>
<div v-if="node.children">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
@check-change="propagateCheckChange">
</tree-node>
</div>
</div>
</template>
<script>
export default {
methods: {
handleCheckChange() {
this.$emit('check-change', this.node)
},
propagateCheckChange(node) {
this.$emit('check-change', node)
}
}
}
</script>
性能优化建议
对于大型树形结构,使用虚拟滚动技术可以显著提高性能:
<template>
<virtual-list
:size="30"
:remain="8"
:data="treeData">
<tree-node
slot-scope="{ item }"
:node="item">
</tree-node>
</virtual-list>
</template>
动态加载数据
实现懒加载功能可以优化初始加载时间:
<el-tree
:load="loadNode"
lazy>
</el-tree>
<script>
export default {
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ name: '根节点' }])
}
if (node.level > 3) return resolve([])
setTimeout(() => {
resolve([
{ name: '子节点' + new Date().getTime() }
])
}, 500)
}
}
}
</script>






