Vue实现菜单权限控制
Vue 菜单权限控制实现方法
基于路由守卫的权限控制
在路由配置中为每个路由添加 meta 字段定义权限标识,通过全局前置守卫验证用户权限。未授权用户跳转至无权限页面或登录页。
// router/index.js
const routes = [
{
path: '/admin',
component: AdminPanel,
meta: { requiresAuth: true, permission: 'admin' }
}
]
router.beforeEach((to, from, next) => {
const userPermissions = store.getters.permissions
if (to.meta.permission && !userPermissions.includes(to.meta.permission)) {
next('/forbidden')
} else {
next()
}
})
动态菜单渲染方案
从后端获取权限数据后,过滤出有权限访问的路由生成菜单。使用 vue-router 的 addRoutes 方法动态注册路由(Vue 2.x)或 router.addRoute(Vue 3)。
// 过滤有权限的路由
function filterRoutes(allRoutes, permissions) {
return allRoutes.filter(route => {
if (route.meta?.permission) {
return permissions.includes(route.meta.permission)
}
return true
})
}
// 添加动态路由
const allowedRoutes = filterRoutes(asyncRoutes, userPermissions)
router.addRoute(allowedRoutes)
Vuex/Pinia 状态管理
在状态管理中存储用户权限信息,通过计算属性控制菜单显示。结合 v-if 或自定义指令实现界面元素权限控制。
// store/modules/user.js
state: {
permissions: ['user']
},
getters: {
hasPermission: state => permission => {
return state.permissions.includes(permission)
}
}
自定义权限指令
创建 v-permission 指令直接控制DOM元素显隐,适用于按钮级权限控制。
// directives/permission.js
export default {
inserted(el, binding, vnode) {
const { value } = binding
const permissions = vnode.context.$store.getters.permissions
if (value && !permissions.includes(value)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
服务端返回菜单结构
后端直接返回已过滤的菜单树结构,前端只需渲染无需再过滤。适合复杂权限体系,保持前后端权限逻辑一致性。
// API请求示例
getUserMenu().then(menuData => {
this.menuItems = menuData
})
实现注意事项
- 路由配置应拆分为基础路由(如登录页)和权限路由
- 权限标识建议使用字符串常量维护
- 按钮级权限推荐使用自定义指令或权限组件包裹
- 首次加载时可通过路由白名单避免权限校验死循环
- 生产环境应结合JWT等认证方案保证权限数据安全性
最佳实践组合方案
- 路由级权限:路由守卫 + 动态路由注册
- 菜单级权限:后端返回过滤后的菜单数据
- 元素级权限:自定义指令 + 权限计算属性
- 状态管理:集中维护权限数据与校验方法
这种分层控制方案既能满足不同颗粒度的权限需求,又能保持代码的可维护性。







