vue怎么实现菜单树
Vue 实现菜单树的常用方法
递归组件实现
递归组件是处理树形结构的常见方式,适合嵌套层级不确定的菜单树。
<template>
<ul>
<li v-for="item in menuData" :key="item.id">
{{ item.name }}
<menu-tree v-if="item.children" :menu-data="item.children"/>
</li>
</ul>
</template>
<script>
export default {
name: 'MenuTree',
props: {
menuData: {
type: Array,
required: true
}
}
}
</script>
使用计算属性处理数据
通过计算属性对原始数据进行处理,添加层级标识等额外信息。
<template>
<div>
<div v-for="item in processedMenu" :key="item.id" :style="{ paddingLeft: item.level * 20 + 'px' }">
{{ item.name }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
menuData: [...] // 原始菜单数据
}
},
computed: {
processedMenu() {
const process = (data, level = 0) => {
return data.map(item => {
return {
...item,
level,
children: item.children ? process(item.children, level + 1) : []
}
})
}
return process(this.menuData)
}
}
}
</script>
第三方库实现
使用成熟的树形组件库如 Element UI 的 el-tree 可以快速实现功能。
<template>
<el-tree
:data="menuData"
:props="defaultProps"
@node-click="handleNodeClick"
/>
</template>
<script>
export default {
data() {
return {
menuData: [...],
defaultProps: {
children: 'children',
label: 'name'
}
}
},
methods: {
handleNodeClick(data) {
console.log(data)
}
}
}
</script>
动态加载实现
对于大数据量的菜单树,可以采用动态加载方式优化性能。
<template>
<ul>
<li v-for="item in visibleMenu" :key="item.id" @click="loadChildren(item)">
{{ item.name }}
<span v-if="item.hasChildren && !item.children">+</span>
<menu-tree v-if="item.children" :menu-data="item.children"/>
</li>
</ul>
</template>
<script>
export default {
name: 'MenuTree',
props: {
menuData: Array
},
computed: {
visibleMenu() {
return this.menuData.filter(item => item.visible !== false)
}
},
methods: {
loadChildren(item) {
if (item.hasChildren && !item.children) {
// 异步加载子菜单
fetchChildren(item.id).then(children => {
this.$set(item, 'children', children)
})
}
}
}
}
</script>
路由集成实现
将菜单树与 vue-router 结合,实现导航功能。
<template>
<div>
<div v-for="item in menuRoutes" :key="item.path">
<router-link :to="item.path">{{ item.meta.title }}</router-link>
<div v-if="item.children" style="margin-left: 20px">
<menu-routes :routes="item.children"/>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MenuRoutes',
props: {
routes: {
type: Array,
required: true
}
},
computed: {
menuRoutes() {
return this.routes.filter(route => route.meta && route.meta.showInMenu)
}
}
}
</script>
以上方法可根据具体需求选择或组合使用,递归组件适合简单场景,第三方库提供更多功能,动态加载优化性能,路由集成实现导航功能。







