vue权限如何实现
Vue 权限实现方案
在 Vue 项目中实现权限控制通常涉及路由权限、按钮权限和接口权限三个方面。以下是具体实现方法:
路由权限控制
路由权限通常通过动态路由和全局路由守卫实现。用户登录后获取权限列表,筛选出有权限的路由并动态添加到路由实例中。
// 在路由配置中标记权限字段
const routes = [
{
path: '/admin',
component: Admin,
meta: { requiresAuth: true, permission: 'admin' }
}
]
// 全局路由守卫
router.beforeEach((to, from, next) => {
const hasPermission = store.getters.permissions.includes(to.meta.permission)
if (to.meta.requiresAuth && !hasPermission) next('/login')
else next()
})
动态添加路由:
// 根据权限过滤路由
const filteredRoutes = asyncRoutes.filter(route => {
return userPermissions.includes(route.meta.permission)
})
router.addRoutes(filteredRoutes)
按钮级权限控制
按钮权限通常通过自定义指令或组件封装实现。

自定义指令方式:
Vue.directive('permission', {
inserted(el, binding, vnode) {
const { value } = binding
const permissions = store.getters.permissions
if (!permissions.includes(value)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
})
// 使用方式
<button v-permission="'user:delete'">删除</button>
组件封装方式:

<template>
<div v-if="checkPermission(permission)">
<slot />
</div>
</template>
<script>
export default {
props: ['permission'],
methods: {
checkPermission(permission) {
return this.$store.getters.permissions.includes(permission)
}
}
}
</script>
接口权限控制
接口权限通常在请求拦截器中实现,通过检查每个请求需要的权限是否与用户权限匹配。
axios.interceptors.request.use(config => {
const requiredPermission = config.meta?.permission
if (requiredPermission) {
const hasPermission = store.getters.permissions.includes(requiredPermission)
if (!hasPermission) return Promise.reject(new Error('无权限访问'))
}
return config
})
权限数据管理
权限数据通常存储在 Vuex 中,与用户信息一起初始化。
// store/modules/user.js
const state = {
permissions: []
}
const mutations = {
SET_PERMISSIONS(state, permissions) {
state.permissions = permissions
}
}
const actions = {
async getUserPermissions({ commit }) {
const res = await api.getPermissions()
commit('SET_PERMISSIONS', res.data)
}
}
后端配合要点
- 用户登录后返回权限标识列表
- 每个路由和接口在后端定义所需权限标识
- 前端根据权限标识控制显示和访问
权限标识通常采用类似 模块:操作 的格式,如 user:add、role:delete。
注意事项
- 权限校验需要前后端同时进行,前端控制仅为体验优化
- 敏感操作必须后端验证权限
- 路由权限建议使用 addRoutes 动态添加
- 按钮权限建议使用自定义指令保持代码简洁






