vue 实现递归
Vue 实现递归组件的方法
在 Vue 中实现递归组件通常用于展示树形结构数据(如目录、评论嵌套等)。递归组件的核心是组件通过名称调用自身。
定义递归组件
递归组件的关键是设置 name 选项,使组件可以在模板中调用自身:
<template>
<div>
<!-- 当前节点内容 -->
<div>{{ node.name }}</div>
<!-- 递归调用 -->
<my-component
v-if="node.children"
v-for="child in node.children"
:node="child"
/>
</div>
</template>
<script>
export default {
name: 'MyComponent', // 必须声明name
props: {
node: Object // 接收递归数据
}
}
</script>
使用动态组件避免循环引用
若遇到组件循环引用问题(如组件A依赖组件B,组件B又依赖组件A),可通过动态组件解决:

<template>
<div>
<component
:is="isChild ? 'MyComponent' : 'OtherComponent'"
:node="node.children"
/>
</div>
</template>
终止条件控制
必须设置递归终止条件,通常通过 v-if 判断子节点是否存在:
<template>
<div>
<div>{{ node.title }}</div>
<my-component
v-if="node.children && node.children.length > 0"
v-for="child in node.children"
:node="child"
/>
</div>
</template>
性能优化建议
对于深层递归,建议添加 v-once 指令缓存静态内容:

<my-component v-once :node="rootNode" />
或通过计算属性预处理数据:
computed: {
normalizedNodes() {
// 预处理数据逻辑
return processNodes(this.node);
}
}
完整示例代码
以下是一个树形菜单的完整实现:
<template>
<ul>
<li v-for="item in treeData" :key="item.id">
{{ item.name }}
<TreeMenu
v-if="item.children && item.children.length"
:treeData="item.children"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeMenu',
props: {
treeData: {
type: Array,
required: true
}
}
}
</script>
使用时传入树形数据:
<TreeMenu :treeData="[
{
id: 1,
name: 'Parent',
children: [
{id: 2, name: 'Child'}
]
}
]"/>
注意事项
- 必须为递归组件设置
name属性 - 确保数据有明确的层级终止条件(如
children为空) - 深层递归可能导致性能问题,建议限制递归深度
- 在 Vue 3 中,
<script setup>语法糖需额外处理组件命名






