vue 实现菜单权限
Vue 实现菜单权限的方法
基于路由守卫的权限控制
在 Vue 项目中,可以通过路由守卫(Navigation Guards)来实现菜单权限控制。这种方式适用于基于角色的权限管理,确保用户只能访问其权限范围内的路由。
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '../store'
Vue.use(Router)
const router = new Router({
routes: [...]
})
router.beforeEach((to, from, next) => {
const hasPermission = store.getters.permissions.includes(to.meta.permission)
if (to.meta.permission && !hasPermission) {
next('/403') // 无权限跳转到403页面
} else {
next()
}
})
动态生成菜单
通过后端返回的权限数据动态生成菜单,通常需要将路由分为基础路由和动态路由两部分。基础路由包括登录页、404页等,动态路由根据用户权限动态添加。
// 过滤异步路由表
export function filterAsyncRoutes(routes, permissions) {
return routes.filter(route => {
if (route.meta && route.meta.permission) {
return permissions.includes(route.meta.permission)
}
return true
})
}
使用 Vuex 管理权限状态
在 Vuex 中存储用户的权限信息,方便全局访问和更新。通常包括用户角色、权限列表等数据。
// store/modules/permission.js
const state = {
permissions: []
}
const mutations = {
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
}
}
const actions = {
generateRoutes({ commit }, permissions) {
return new Promise(resolve => {
const accessedRoutes = filterAsyncRoutes(asyncRoutes, permissions)
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
基于指令的权限控制
对于按钮级别的权限控制,可以创建自定义指令 v-permission,在模板中直接使用。
// directives/permission.js
import store from '@/store'
function checkPermission(el, binding) {
const { value } = binding
const permissions = store.getters && store.getters.permissions
if (value && value instanceof Array) {
const hasPermission = permissions.some(permission => {
return value.includes(permission)
})
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`需要权限数组! 如 v-permission="['admin','editor']"`)
}
}
export default {
inserted(el, binding) {
checkPermission(el, binding)
},
update(el, binding) {
checkPermission(el, binding)
}
}
菜单渲染优化
在渲染菜单时,可以根据权限过滤菜单项,只显示用户有权限访问的菜单。这通常需要在菜单组件中处理。
// 递归过滤菜单
function filterMenu(menu, permissions) {
return menu.filter(item => {
if (item.children) {
item.children = filterMenu(item.children, permissions)
}
return !item.meta || !item.meta.permission || permissions.includes(item.meta.permission)
})
}
权限数据格式建议
后端返回的权限数据格式应该与前端路由配置保持一致,通常建议使用字符串数组形式,如 ['user:add', 'user:edit']。路由配置中可以添加 meta 字段存储权限标识。
// 路由配置示例
{
path: '/user',
component: Layout,
meta: {
title: '用户管理',
permission: 'user:manage'
},
children: [...]
}
错误处理与边界情况
需要考虑用户直接输入无权限路由地址的情况,以及权限变更时的处理。建议添加全局错误页面和权限变更的监听机制。
// 监听权限变化
watch: {
'store.getters.permissions'(newVal) {
this.generateRoutes(newVal)
}
}
以上方法可以根据项目需求组合使用,实现完整的菜单权限控制体系。实际应用中,建议将权限逻辑封装为独立模块,便于维护和扩展。







