vue实现菜单调用
Vue 实现动态菜单的常见方法
基于路由配置生成菜单
Vue Router 的路由配置可以天然转化为菜单结构,适合权限与路由绑定的系统:
// router/index.js
const routes = [
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: { title: '控制台', icon: 'el-icon-monitor' }
},
{
path: '/user',
name: 'User',
component: User,
meta: { title: '用户管理', icon: 'el-icon-user' },
children: [
{ path: 'list', component: UserList, meta: { title: '用户列表' } }
]
}
]
<!-- MenuComponent.vue -->
<template>
<el-menu :router="true">
<template v-for="route in $router.options.routes">
<el-submenu
v-if="route.children"
:index="route.path"
:key="route.path">
<template #title>
<i :class="route.meta.icon"></i>
<span>{{ route.meta.title }}</span>
</template>
<el-menu-item
v-for="child in route.children"
:key="child.path"
:index="route.path + '/' + child.path">
{{ child.meta.title }}
</el-menu-item>
</el-submenu>
<el-menu-item v-else :index="route.path" :key="route.path">
<i :class="route.meta.icon"></i>
<span>{{ route.meta.title }}</span>
</el-menu-item>
</template>
</el-menu>
</template>
后端返回菜单数据方案
适合需要动态权限控制的系统,通过 API 获取菜单数据:

// 示例数据结构
[
{
id: 1,
name: "System",
title: "系统管理",
icon: "setting",
children: [
{ id: 11, name: "User", title: "用户管理", path: "/user" }
]
}
]
<script>
export default {
data() {
return {
menuItems: []
}
},
async created() {
const res = await axios.get('/api/menus')
this.menuItems = res.data
}
}
</script>
<template>
<el-menu>
<template v-for="item in menuItems">
<el-submenu
v-if="item.children"
:index="item.id.toString()"
:key="item.id">
<template #title>
<i :class="'el-icon-' + item.icon"></i>
<span>{{ item.title }}</span>
</template>
<el-menu-item
v-for="child in item.children"
:key="child.id"
:index="child.path">
{{ child.title }}
</el-menu-item>
</el-submenu>
<el-menu-item v-else :index="item.path" :key="item.id">
<i :class="'el-icon-' + item.icon"></i>
<span>{{ item.title }}</span>
</el-menu-item>
</template>
</el-menu>
</template>
递归组件实现多级菜单
对于不确定层级的深度嵌套菜单,可使用递归组件:
<!-- RecursiveMenu.vue -->
<template>
<el-submenu
v-if="item.children"
:index="item.path">
<template #title>
<i :class="item.icon"></i>
<span>{{ item.title }}</span>
</template>
<recursive-menu
v-for="child in item.children"
:key="child.path"
:item="child"/>
</el-submenu>
<el-menu-item v-else :index="item.path">
<i :class="item.icon"></i>
<span>{{ item.title }}</span>
</el-menu-item>
</template>
<script>
export default {
name: 'RecursiveMenu',
props: ['item']
}
</script>
权限过滤实现
结合权限系统过滤显示的菜单项:

computed: {
filteredMenus() {
return this.menuItems.filter(menu => {
return this.$hasPermission(menu.permission)
})
}
}
菜单状态保持
使用 Vuex 或 Pinia 存储菜单展开状态:
// store/modules/menu.js
const state = {
openedMenus: ['1'] // 默认展开的菜单ID
}
const mutations = {
TOGGLE_MENU(state, menuId) {
const index = state.openedMenus.indexOf(menuId)
if (index > -1) {
state.openedMenus.splice(index, 1)
} else {
state.openedMenus.push(menuId)
}
}
}
响应式处理
监听路由变化高亮当前菜单项:
watch: {
'$route.path': {
immediate: true,
handler(path) {
this.$refs.menu.activeIndex = path
}
}
}
通过组合这些方法,可以构建出适应不同业务场景的 Vue 菜单系统。实际实现时应根据项目需求选择路由映射、后端动态配置或混合模式。






