vue树形展示实现
使用 el-tree 组件实现
Element UI 提供了 el-tree 组件用于展示树形结构数据。需要安装 Element UI 并引入 el-tree 组件。
安装 Element UI:
npm install element-ui
在 Vue 文件中使用:
<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>
自定义递归组件实现
对于不使用 UI 框架的情况,可以通过递归组件实现树形展示。
创建 TreeItem.vue 组件:
<template>
<div>
<div @click="toggle">
{{ node.label }}
</div>
<div v-show="isOpen" v-if="node.children">
<TreeItem
v-for="child in node.children"
:key="child.id"
:node="child"
/>
</div>
</div>
</template>
<script>
export default {
name: 'TreeItem',
props: {
node: Object
},
data() {
return {
isOpen: false
}
},
methods: {
toggle() {
this.isOpen = !this.isOpen
}
}
}
</script>
在父组件中使用:

<template>
<TreeItem :node="treeData" />
</template>
<script>
import TreeItem from './TreeItem.vue'
export default {
components: { TreeItem },
data() {
return {
treeData: {
label: '根节点',
children: [
{ label: '子节点1' },
{
label: '子节点2',
children: [
{ label: '孙子节点' }
]
}
]
}
}
}
}
</script>
使用第三方库 vue-treeselect
vue-treeselect 是一个功能丰富的树形选择组件,支持搜索、多选等功能。
安装:
npm install @riophae/vue-treeselect
使用示例:
<template>
<treeselect
v-model="value"
:multiple="true"
:options="options"
/>
</template>
<script>
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
components: { Treeselect },
data() {
return {
value: null,
options: [ {
id: 'a',
label: 'a',
children: [ {
id: 'aa',
label: 'aa'
} ]
} ]
}
}
}
</script>
性能优化建议
对于大型树形数据,应考虑以下优化措施:

使用虚拟滚动技术,只渲染可视区域内的节点。vue-virtual-scroll-tree 是一个不错的选择。
实现懒加载功能,当展开父节点时才加载子节点数据。el-tree 支持 lazy 模式和 load 方法。
对于静态数据,可以在 created 钩子中对数据进行预处理,添加索引或扁平化处理以便快速访问。
动态加载数据示例
el-tree 支持动态加载节点数据:
<template>
<el-tree
:props="props"
:load="loadNode"
lazy
></el-tree>
</template>
<script>
export default {
data() {
return {
props: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
}
}
},
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
// 返回根节点
return resolve([{ name: '区域1' }, { name: '区域2' }])
}
if (node.level >= 1) {
// 模拟异步加载
setTimeout(() => {
resolve([
{ name: `${node.data.name}-子区域1`, leaf: true },
{ name: `${node.data.name}-子区域2` }
])
}, 500)
}
}
}
}
</script>






