vue实现树目录
Vue 实现树形目录
在 Vue 中实现树形目录可以通过递归组件或第三方库(如 element-ui 的 el-tree)完成。以下是两种常见实现方式:
递归组件实现
递归组件适合自定义程度高的树形结构,通过组件调用自身实现嵌套渲染。
<template>
<div>
<tree-node :node="treeData" @on-click="handleNodeClick"></tree-node>
</div>
</template>
<script>
export default {
components: {
TreeNode: {
name: 'TreeNode',
props: ['node'],
template: `
<ul>
<li @click.stop="toggle">
{{ node.label }}
<span v-if="hasChildren">[{{ isOpen ? '-' : '+' }}]</span>
</li>
<template v-if="isOpen && hasChildren">
<tree-node
v-for="child in node.children"
:key="child.id"
:node="child"
@on-click="$emit('on-click', $event)"
/>
</template>
</ul>
`,
data() {
return { isOpen: false }
},
computed: {
hasChildren() {
return this.node.children && this.node.children.length
}
},
methods: {
toggle() {
if (this.hasChildren) {
this.isOpen = !this.isOpen
} else {
this.$emit('on-click', this.node)
}
}
}
}
},
data() {
return {
treeData: {
id: 1,
label: 'Root',
children: [
{ id: 2, label: 'Child 1' },
{
id: 3,
label: 'Child 2',
children: [
{ id: 4, label: 'Grandchild 1' }
]
}
]
}
}
},
methods: {
handleNodeClick(node) {
console.log('Clicked node:', node)
}
}
}
</script>
使用 Element UI 的 el-tree
对于快速实现标准化树形结构,可以使用现成的 UI 库组件。
<template>
<el-tree
:data="treeData"
:props="defaultProps"
@node-click="handleNodeClick"
/>
</template>
<script>
export default {
data() {
return {
treeData: [{
label: 'Level 1',
children: [{
label: 'Level 2',
children: [{
label: 'Level 3'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
}
},
methods: {
handleNodeClick(data) {
console.log('Clicked node:', data)
}
}
}
</script>
动态加载数据
当需要异步加载节点数据时,可以结合 API 请求实现。
<template>
<el-tree
:props="props"
:load="loadNode"
lazy
/>
</template>
<script>
export default {
data() {
return {
props: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
}
}
},
methods: {
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'Region' }])
}
if (node.level > 3) return resolve([])
setTimeout(() => {
const data = Array(3).fill(null).map((_, i) => ({
name: `Zone ${node.level}-${i}`,
leaf: node.level >= 2
}))
resolve(data)
}, 500)
}
}
}
</script>
自定义节点内容
通过 scoped slot 可以完全自定义每个节点的渲染方式。
<template>
<el-tree :data="data">
<template #default="{ node, data }">
<span class="custom-node">
<span>{{ node.label }}</span>
<span v-if="!node.isLeaf">
({{ node.childNodes.length }})
</span>
</span>
</template>
</el-tree>
</template>
关键注意事项
- 递归组件需要设置
name属性才能在模板中调用自身 - 树形数据通常需要唯一
key标识每个节点 - 大数据量时考虑虚拟滚动优化性能
- 复杂交互(如拖拽、复选框)建议直接使用成熟组件库实现
以上方案可根据项目需求选择,自定义组件适合特殊UI需求,而UI库组件能快速实现标准功能。







