Vue 项目 菜单权限及按钮级权限控制

实现思路

1.页面展示需要鉴权的所有按钮,需要先鉴权菜单权限的显示与隐藏。

2.勾选每个角色或者用户所能看的权限保存在数据库。该权限数据是一个权限字段的数组。

3.全局自定义指令(directive)控制按钮权限数据的方法,登入时获取后端传来的按钮权限数组。

4.在每个按钮中调用该指令,并传入该操作的权限字段和后端保存的权限字段进行匹配,能匹配则该操作按钮可显示

具体代码如下

  1. 获取登录用户所有权限
// 获取权限菜单(存在store下modules下user.js的actions中)
 getMenuTree ({ commit, state }) {
   return new Promise((resolve, reject) => {
     getMenuTree(state.token).then(response => {
       const data = response.result
       if (!data) {
         reject('验证失败,请重新登录')
       }
       // 存菜单结构
       commit('SET_ROLES', data)
       // 重置按钮权限
       btns = []
       const btn = findAllBtn(data)
       // 存所有按钮权限
       commit('SET_BUTTONS', btn)
       resolve(data)
     }).catch(error => {
       reject(error)
     })
   })
 }
// 递归获取按钮list
let btns = []
export function findAllBtn (list) {
 list.forEach(val => {
 // 与后台协商所有菜单资源(resCode)下的type是1表菜单,2为按钮
   if (val.type === '1') {
     if (val.children && val.children.length > 0) {
       findAllBtn(val.children)
     }
   } else {
     btns.push(val.reCode)
   }
 })
}
  1. 对比菜单权限的方法
在store下modules下新建一个permission.js(获取最终动态权限菜单)
/**
* @param  {Array} userRouter 后台返回的用户权限json
* @param  {Array} allRouter  前端配置好的所有动态路由的集合
* @return {Array} realRoutes 过滤后的路由
*/
export function recursionRouter (userRouter = [], allRouter = []) {
 let realRoutes = []
 allRouter.forEach(val => {
   userRouter.forEach(item => {
     if (val.path.includes('/')) {
       if (item.resCode === val.path.split('/')[1]) {
         val.children = recursionRouter(item.children, val.children)
         realRoutes.push(val)
       }
     } else {
       if (item.resCode === val.path) {
         if (item.children && item.children.length > 0) {
           val.children = recursionRouter(item.children, val.children)
         }
         realRoutes.push(val)
       }
     }
   })
 })
 realRoutes.push({ path: '*', redirect: '/404', isShow: true })
 // console.log(222, realRoutes)
 return realRoutes
}
// asyncRouterMap本地配置好的所有动态路由的集合
const actions = {
 generateRoutes ({ commit }, roles) {
   return new Promise(resolve => {
     let accessedRoutes = recursionRouter(roles, [...asyncRouterMap])
     commit('SET_ROUTES', accessedRoutes)
     resolve(accessedRoutes)
   })
 }
}

对比菜单权限需要在全局路由守卫中如下操作

router.beforeEach(async (to, from, next) => {
 // 确定用户是否已登录
 const hasToken = getToken()
 // 判断是否有token
 if (hasToken) {
   // 运营端登录
   if (to.path === '/login') {
     // 如果已登录,则重定向到主页
     next({ path: '/' })
     NProgress.done()
   } else {
     // 确定用户是否已获得了他的权限角色
     const hasRoles = store.getters.roles && store.getters.roles.length > 0
     if (hasRoles) {
       next()
     } else {
       // 角色必须是对象数组
       const roles = await store.dispatch('user/getMenuTree')
         // 根据角色生成可访问路由映射
         const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
         // 清空静态路由
         resetRouter()
         // 动态添加可访问路由
         router.addRoutes(accessRoutes)
         // hack 方法,以确保addRoutes是完整的
         // 设置replace: true,这样导航就不会留下历史记录
         next({ ...to, replace: true })
     }
   }
 } else {
   // 在免登录白名单,直接进入
   if (whiteList.indexOf(to.path) !== -1) {
     next()
   } else {
     // 没有访问权限的其他页面被重定向到登录页面
     next(`/login?redirect=${to.path}`)
     NProgress.done()
   }
 }
})
  1. 全局自定义指令
// 需要全局注入(即在main.js引入)
import Vue from 'vue'
import store from '@/store'
/**
 * 使用:v-permission="'resCode'"
 *   resCode 按钮资源(即路由path)
 * **/
Vue.directive('permission', {
  inserted (el, vDir) {
    let btnPermission = store.getters.buttons
    if (vDir.value) {
      if (!btnPermission.includes(vDir.value)) {
        el.parentNode.removeChild(el)
      }
    }
  }
})
  1. 页面中使用
<el-button type="primary" @click="roleExport" v-permission="'ent-role-export'">导出</el-button>

如图

初始在这里插入图片描述
取消权限后
在这里插入图片描述
在这里插入图片描述


相关文章

基于elementUI中table组件二次封装(Vue项目)


axios二次封装,接口统一存放,满足RESTful风格


keep-alive不能缓存多层级路由(vue-router)菜单问题解决


基于ElementUi再次封装基础组件文档

  • 5
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Vue3 中,你可以通过自定义指令或组件的方式来封装权限菜单权限按钮。 1. 自定义指令 你可以通过自定义指令来实现权限按钮的封装。例如,你可以创建一个名为 `v-permission` 的指令,然后在需要控制权限按钮上使用该指令。在指令中,你可以通过判断用户是否拥有相应的权限控制按钮的显示或隐藏。 示例代码: ```vue <template> <button v-permission="'edit'">编辑</button> </template> <script> export default { directives: { permission: { mounted(el, binding) { const permission = binding.value; const hasPermission = checkPermission(permission); if (!hasPermission) { el.style.display = 'none'; } } } } } </script> ``` 2. 组件 你也可以通过组件的方式来封装权限菜单权限按钮。例如,你可以创建一个名为 `PermissionMenu` 的组件,然后在该组件中根据用户是否拥有相应的权限来动态生成菜单。 示例代码: ```vue <template> <ul> <li v-for="item in menu" :key="item.path"> <router-link v-if="hasPermission(item.permission)" :to="item.path">{{ item.title }}</router-link> </li> </ul> </template> <script> export default { data() { return { menu: [ { path: '/', title: '首页', permission: 'home' }, { path: '/user', title: '用户管理', permission: 'user' }, { path: '/role', title: '角色管理', permission: 'role' } ] } }, methods: { hasPermission(permission) { return checkPermission(permission); } } } </script> ``` 无论是自定义指令还是组件,都需要在代码中实现权限的判断逻辑,以保证权限的正确控制

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wocwin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值