实现树形菜单vue
实现树形菜单的Vue方案
递归组件实现
创建递归组件TreeMenu.vue,通过组件自身调用自身实现无限层级渲染:
<template>
<ul>
<li v-for="item in data" :key="item.id">
{{ item.name }}
<TreeMenu v-if="item.children" :data="item.children"/>
</li>
</ul>
</template>
<script>
export default {
name: 'TreeMenu',
props: {
data: Array
}
}
</script>
数据格式要求
树形数据应满足以下结构:
const treeData = [
{
id: 1,
name: '父节点',
children: [
{
id: 2,
name: '子节点1'
},
{
id: 3,
name: '子节点2',
children: [...]
}
]
}
]
添加展开/折叠功能
通过v-show和点击事件控制子级显示:
<template>
<ul>
<li v-for="item in data" :key="item.id">
<span @click="toggle(item)">
{{ item.expanded ? '▼' : '►' }} {{ item.name }}
</span>
<TreeMenu
v-if="item.children"
v-show="item.expanded"
:data="item.children"/>
</li>
</ul>
</template>
<script>
export default {
methods: {
toggle(item) {
this.$set(item, 'expanded', !item.expanded)
}
}
}
</script>
使用第三方库
对于复杂需求,可考虑以下成熟方案:
vue-tree-halower:支持拖拽、复选框等功能element-ui的el-tree组件ant-design-vue的a-tree组件
样式优化建议
添加CSS增强视觉效果:
ul {
list-style: none;
padding-left: 20px;
}
li {
cursor: pointer;
line-height: 1.8;
}
动态加载数据
实现异步加载子节点:
async loadChildren(item) {
if(!item.children) {
const res = await api.getChildren(item.id)
this.$set(item, 'children', res.data)
}
this.$set(item, 'expanded', true)
}
事件处理
通过$emit向上传递节点事件:
<span @click="$emit('node-click', item)">
{{ item.name }}
</span>
性能优化
对于大型树结构:
- 使用虚拟滚动(如
vue-virtual-scroller) - 实现懒加载
- 避免深度响应式,对静态数据使用
Object.freeze
以上方案可根据实际需求组合使用,基础递归组件适合简单场景,复杂业务推荐基于成熟组件库扩展。







