vue实现递归树
Vue 实现递归树的方法
递归树是一种常见的数据结构,用于展示具有层级关系的数据。在 Vue 中,可以通过组件递归调用的方式实现递归树。以下是几种实现方法:
使用组件递归调用
创建一个递归组件,组件内部调用自身来实现树的递归渲染。假设数据结构如下:
const treeData = [
{
label: 'Node 1',
children: [
{
label: 'Node 1.1',
children: []
}
]
}
]
递归组件的实现:
<template>
<ul>
<li v-for="(item, index) in data" :key="index">
{{ item.label }}
<tree-node v-if="item.children && item.children.length" :data="item.children" />
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
data: {
type: Array,
required: true
}
}
}
</script>
使用动态组件名称
如果组件名称需要动态绑定,可以使用 :is 动态绑定组件名称:
<template>
<ul>
<li v-for="(item, index) in data" :key="index">
{{ item.label }}
<component
v-if="item.children && item.children.length"
:is="componentName"
:data="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
data: {
type: Array,
required: true
}
},
data() {
return {
componentName: 'TreeNode'
}
}
}
</script>
使用插槽实现自定义内容
如果需要自定义每个节点的内容,可以通过插槽实现:
<template>
<ul>
<li v-for="(item, index) in data" :key="index">
<slot :item="item">
{{ item.label }}
</slot>
<tree-node
v-if="item.children && item.children.length"
:data="item.children"
>
<template v-slot="{ item }">
<span style="color: red">{{ item.label }}</span>
</template>
</tree-node>
</li>
</ul>
</template>
添加交互功能
为树节点添加展开/折叠功能:
<template>
<ul>
<li v-for="(item, index) in data" :key="index">
<span @click="toggle(item)">
{{ item.expanded ? '−' : '+' }} {{ item.label }}
</span>
<tree-node
v-if="item.children && item.children.length && item.expanded"
:data="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeNode',
props: {
data: {
type: Array,
required: true
}
},
methods: {
toggle(item) {
this.$set(item, 'expanded', !item.expanded)
}
}
}
</script>
使用计算属性优化渲染
如果树的数据较大,可以通过计算属性优化渲染性能:
<script>
export default {
name: 'TreeNode',
props: {
data: {
type: Array,
required: true
}
},
computed: {
normalizedData() {
return this.data.map(item => ({
...item,
expanded: item.expanded || false
}))
}
}
}
</script>
以上方法可以根据实际需求灵活组合使用,实现功能丰富且高效的递归树组件。







