vue 实现菜单权限
实现菜单权限的基本思路
在Vue中实现菜单权限通常涉及前端路由权限控制和动态菜单渲染。核心是通过用户角色或权限标识过滤路由表,生成可访问的菜单列表。
权限数据准备
后端需要提供用户权限数据,通常以角色标识(如admin)或权限码列表(如['user:add', 'menu:edit'])的形式返回。建议在登录后通过接口获取并存储在Vuex或Pinia中。
// 示例权限数据结构
{
roles: ['admin'],
permissions: ['system:user', 'system:role']
}
路由配置拆分
将路由分为常量路由(如登录页)和动态路由。动态路由需要添加meta字段标记所需权限:

const dynamicRoutes = [
{
path: '/user',
meta: {
title: '用户管理',
roles: ['admin'],
permissions: ['system:user']
}
}
]
路由拦截处理
在全局路由守卫中校验权限,推荐使用addRoutes(Vue Router 3.x)或addRoute(Vue Router 4.x)动态添加路由:
router.beforeEach((to, from, next) => {
const hasPermission = checkPermission(to.meta)
if (!hasPermission) return next('/403')
next()
})
function checkPermission(routeMeta) {
const userRoles = store.getters.roles
if (routeMeta?.roles) {
return userRoles.some(role => routeMeta.roles.includes(role))
}
return true
}
动态菜单生成
基于过滤后的路由表生成菜单,使用递归组件处理嵌套路由:

<template>
<el-menu>
<MenuItem
v-for="route in permittedRoutes"
:key="route.path"
:item="route"
/>
</el-menu>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['permittedRoutes'])
}
}
</script>
权限指令封装
对于按钮级权限,可封装v-permission指令:
Vue.directive('permission', {
inserted(el, binding, vnode) {
const { value } = binding
const permissions = vnode.context.$store.getters.permissions
if (!permissions.includes(value)) {
el.parentNode.removeChild(el)
}
}
})
服务端控制方案
更安全的方案是后端返回完整菜单结构,前端直接渲染:
// 后端返回示例
[
{
path: "/system",
children: [
{ path: "user", meta: { title: "用户管理" } }
]
}
]
缓存处理策略
用户权限变更时需要清除路由缓存,可在退出登录时重置路由实例:
function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher
}
注意事项
- 敏感路由应始终在后端进行二次校验
- 前端权限控制不能替代后端API权限验证
- 动态路由可能导致刷新页面404,需配置服务器回退到index.html
- 使用Vue Router 4.x需注意
addRoute的API变化
通过以上方法可以实现细粒度的菜单权限控制,根据实际项目复杂度选择适合的方案组合。






