vue实现的菜单管理
Vue 实现菜单管理方案
基于 Vue Router 的动态路由
动态路由结合后端接口实现菜单权限控制。通过接口获取用户权限菜单列表,格式化后动态添加到路由配置中。
// 动态路由示例代码
const router = new VueRouter({
routes: [] // 初始为空
})
// 获取菜单数据后处理
api.getMenus().then(menus => {
const dynamicRoutes = formatRoutes(menus)
router.addRoutes(dynamicRoutes)
})
function formatRoutes(menus) {
return menus.map(menu => ({
path: menu.path,
component: () => import(`@/views/${menu.component}.vue`),
meta: { title: menu.title }
}))
}
递归组件实现多级菜单
使用 Vue 的递归组件特性处理无限层级菜单结构,适合企业级后台系统的复杂菜单需求。
<!-- 递归菜单组件示例 -->
<template>
<el-submenu v-if="hasChildren" :index="menu.id">
<template #title>{{ menu.title }}</template>
<menu-item
v-for="child in menu.children"
:key="child.id"
:menu="child"
/>
</el-submenu>
<el-menu-item v-else :index="menu.id">
{{ menu.title }}
</el-menu-item>
</template>
<script>
export default {
name: 'MenuItem',
props: {
menu: Object
},
computed: {
hasChildren() {
return this.menu.children && this.menu.children.length
}
}
}
</script>
状态管理集成
将菜单状态纳入 Vuex 统一管理,便于跨组件访问和状态持久化。
// store/modules/menu.js
export default {
state: {
menus: [],
activeMenu: ''
},
mutations: {
SET_MENUS(state, menus) {
state.menus = menus
},
SET_ACTIVE_MENU(state, path) {
state.activeMenu = path
}
},
actions: {
async fetchMenus({ commit }) {
const menus = await api.getMenus()
commit('SET_MENUS', menus)
}
}
}
菜单数据格式示例
推荐采用标准化数据结构,便于前端处理和渲染。
{
"id": "1",
"title": "系统管理",
"icon": "el-icon-setting",
"path": "/system",
"component": "Layout",
"children": [
{
"id": "1-1",
"title": "用户管理",
"path": "/system/user",
"component": "User"
}
]
}
权限控制实现
结合路由守卫实现菜单访问权限控制,未授权菜单自动隐藏或拦截访问。
// 路由守卫示例
router.beforeEach((to, from, next) => {
const hasPermission = store.getters.menus.some(
menu => menu.path === to.path
)
if (!hasPermission && to.path !== '/login') {
next('/403')
} else {
next()
}
})
响应式菜单优化
针对移动端添加菜单折叠功能,使用 CSS 媒体查询实现响应式布局。
<template>
<el-menu
:collapse="isCollapse"
@select="handleSelect"
>
<!-- 菜单内容 -->
</el-menu>
</template>
<script>
export default {
data() {
return {
isCollapse: false
}
},
methods: {
handleCollapse() {
this.isCollapse = !this.isCollapse
}
}
}
</script>
<style>
@media (max-width: 768px) {
.el-menu {
width: 64px;
}
}
</style>
面包屑导航集成
根据当前路由自动生成面包屑导航,提升用户体验。
computed: {
breadcrumbs() {
const matched = this.$route.matched
return matched.map(route => ({
title: route.meta.title,
path: route.path
}))
}
}
菜单图标方案
支持多种图标引入方式,推荐使用 SVG 图标保证清晰度。
<template>
<el-menu-item>
<svg-icon v-if="menu.icon" :icon-class="menu.icon" />
<span slot="title">{{ menu.title }}</span>
</el-menu-item>
</template>
性能优化建议
对于大型菜单系统,采用虚拟滚动技术优化渲染性能。
<template>
<virtual-list
:size="48"
:remain="10"
:data="menus"
>
<menu-item
v-for="menu in menus"
:key="menu.id"
:menu="menu"
/>
</virtual-list>
</template>






