vue递归实现多级菜单
递归实现多级菜单的核心思路
Vue中递归组件通过组件自身调用自身实现嵌套结构,适合处理不确定层级的数据(如多级菜单)。关键在于组件名称的注册和递归终止条件。
基础组件结构
-
定义递归组件
组件需设置name属性,模板内通过name直接引用自身:<template> <ul> <li v-for="item in menuData" :key="item.id"> {{ item.title }} <Menu v-if="item.children" :menu-data="item.children"/> </li> </ul> </template> <script> export default { name: 'Menu', // 必须声明name props: ['menuData'] } </script> -
数据格式示例
菜单数据通常为嵌套结构:
const menuData = [ { id: 1, title: '一级菜单', children: [ { id: 11, title: '二级菜单' } ] } ]
动态组件方案(避免死循环)
通过v-for和条件渲染控制递归深度:
<template>
<ul>
<li v-for="item in menuData" :key="item.id">
{{ item.title }}
<template v-if="item.children?.length">
<Menu :menu-data="item.children"/>
</template>
</li>
</ul>
</template>
性能优化建议
-
添加终止条件
通过max-depth属性限制递归层级:
<Menu :menu-data="data" :max-depth="5"/> -
使用
v-memo缓存
Vue 3中可对静态部分进行优化:<li v-for="item in menuData" :key="item.id" v-memo="[item.id]">
完整示例代码
<template>
<ul class="menu">
<li v-for="item in menuData" :key="item.id">
<div @click="toggle(item)">
{{ item.title }}
<span v-if="hasChildren(item)">▶</span>
</div>
<Menu
v-if="item.children && item.expanded"
:menu-data="item.children"
:max-depth="maxDepth - 1"
/>
</li>
</ul>
</template>
<script>
export default {
name: 'Menu',
props: {
menuData: Array,
maxDepth: { type: Number, default: 10 }
},
methods: {
hasChildren(item) {
return item.children?.length > 0
},
toggle(item) {
if (this.hasChildren(item)) {
item.expanded = !item.expanded
}
}
}
}
</script>
样式处理技巧
使用CSS控制缩进和动画效果:
.menu ul {
padding-left: 20px;
transition: all 0.3s;
}
.menu li {
list-style: none;
cursor: pointer;
}
注意事项
- 避免循环引用导致栈溢出,确保数据没有环形引用
- 大数据量时考虑虚拟滚动(如使用
vue-virtual-scroller) - 通过Vue DevTools检查组件层级是否合理






