iview权限管理怎么实现,分配权限操作是怎样

Admin 2022-05-24 群英技术资讯 545 次浏览

这篇文章给大家分享的是iview权限管理怎么实现,分配权限操作是怎样。小编觉得挺实用的,因此分享给大家做个参考,文中的介绍得很详细,而要易于理解和学习,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。


目录
  • iview-admin2.0自带的权限管理
  • 根据权限控制组件展示
    • 自定义auth指令
    • 自定义auth组件
  • 总结

    iview-admin2.0自带的权限管理

    iview-admin2.0自带权限管理,可以通过设置路由的meta对象的参数access来分配权限。
    默认的角色是super_admin和admin,现在我们给文档这个侧边栏项目分配一个只有user才能查看的权限

      {
        path: '',
        name: 'doc',
        meta: {
          title: '文档',
          href: 'https://lison16.github.io/iview-admin-doc/#/',
          icon: 'ios-book',
          access: ['user']
        }
      },
    

    侧边栏就不会显示文档这个栏目了。在src/store/module/app.js中获取menuList,这个就是侧边栏的list

      getters: {
        menuList: (state, getters, rootState) => getMenuByRouter(routers, rootState.user.access),
        errorCount: state => state.errorList.length
      },
    
    

    这个getter方法主要是执行了getMenuByRouter,接着查看src/libs/util.js找到具体代码

    /**
     * @param {Array} list 通过路由列表得到菜单列表
     * @returns {Array}
     */
    export const getMenuByRouter = (list, access) => {
      let res = []
      forEach(list, item => {
        if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
          let obj = {
            icon: (item.meta && item.meta.icon) || '',
            name: item.name,
            meta: item.meta
          }
          if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) {
            obj.children = getMenuByRouter(item.children, access)
          }
          if (item.meta && item.meta.href) obj.href = item.meta.href
          if (showThisMenuEle(item, access)) res.push(obj)
        }
      })
      return res
    }
    
    const showThisMenuEle = (item, access) => {
      if (item.meta && item.meta.access && item.meta.access.length) {
        if (hasOneOf(item.meta.access, access)) return true
        else return false
      } else return true
    }
    
    

    到这里,access判断权限的过程就比较明白了。代码会获取state里存放的用户信息,主要是access,然后和路由允许的access进行比对,如果用户的access在路由access列表允许的范围内就确权,例如用户access的['admin','super_admin'],但是我们把文档的access设置为['user'],

    hasOneOf(['admin','super_admin'],['user']) // false,鉴权失败
    

    hasOneOf是iview-admin的工具方法。用于判断要查询的数组是否至少有一个元素包含在目标数组中,详细代码放在底部。

    根据权限控制组件展示

    一般我们还需要根据权限去控制页面元素的展示,比如按钮。有两种方法,一种是自定义auth指令,或者自定义一个鉴权组件用来包裹需要鉴权的元素。

    自定义auth指令

    iview-admin把自定义指令统一放在src/directive文件夹下,directives.js文件负责引入单独定义在各个文件的自定义指令,统一导出。我们实现一个auth指令:

    import draggable from './module/draggable'
    import clipboard from './module/clipboard'
    import auth from './module/auth'
    const directives = {
      draggable,
      clipboard,
      auth
    }
    export default directives
    

    然后在src/directive/index.js中导出了一个importDirective方法,入参是Vue,逻辑是注册指令。

    import directive from './directives'
    
    const importDirective = Vue => {
      /**
       * 拖拽指令 v-draggable="options"
       * options = {
       *  trigger: /这里传入作为拖拽触发器的CSS选择器/,
       *  body:    /这里传入需要移动容器的CSS选择器/,
       *  recover: /拖动结束之后是否恢复到原来的位置/
       * }
       */
      Vue.directive('draggable', directive.draggable)
      /**
       * clipboard指令 v-draggable="options"
       * options = {
       *  value:    /在输入框中使用v-model绑定的值/,
       *  success:  /复制成功后的回调/,
       *  error:    /复制失败后的回调/
       * }
       */
      Vue.directive('clipboard', directive.clipboard)
      Vue.directive('auth', directive.auth) 
    }
    
    export default importDirective
    
    

    这个importDirective方法在main.js里面被用到了,并且把真实的Vue传入做为入参。

    import importDirective from '@/directive'
    /**
     * 注册指令
     */
    importDirective(Vue)
    ...
    

    编辑src/directive/module/auth.js

    import store from '@/store'
    export default {
      inserted: (el, binding, vnode) => {
        const value = binding.value
        const access = store.state.user.access
        if (access.indexOf(value) === -1) {
          el.remove()
        }
      }
    }
    

    我们新增一个auth指令,并导出。在注入的时候进行权限判断,如果确权成功就不做什么,如果失败就把元素删除。
    使用试试,拿顶部的折叠菜单按钮做例子,beader-bar.vue

    <template>
      <div class="header-bar">
        <sider-trigger v-auth="'admin'" :collapsed="collapsed" icon="md-menu" @on-change="handleCollpasedChange"></sider-trigger>
        ...
      </div>
    </template>
    

    当v-auth="'admin'"的时候显示按钮,如果是user则会隐藏按钮。

    自定义auth组件

    也可以通过自定义auth组件的方式来实现,创建一个函数式组件auth.vue

    <script>
    import store from '@/store'
    export default {
      functional: true,
      props: {
        authority: {
          type: String,
          require: true
        }
      },
      render (h, context) {
        const { props, scopedSlots } = context
        const access = store.state.user.access
        return access.indexOf(props.authority) > -1 ? scopedSlots.default() : null
      }
    }
    </script>
    

    如果确权成功就返回slot,否则返回null,这样被auth包裹的元素就不会展现了。然后把auth.vue注册为全局组件,免得每次使用都要import一下。编辑main.js

    import Auth from '_c/auth/auth.vue'
    // 注册组件
    Vue.component('Auth',Auth)
    

    使用的时候直接用auth包裹组件即可

    <template>
      <div class="header-bar">
        <Auth authority="user">
          <sider-trigger :collapsed="collapsed" icon="md-menu" @on-change="handleCollpasedChange"></sider-trigger>
        </Auth>
      </div>
    </template>
    

    总结

    不论是用组件式的写法还是自定义指令都能实现,组件的方式实现要写的代码多一点,用自定义指令比较灵活,此外有一点不同,自定义指令如果确权失败,是把元素直接删除掉了,所以此时如果再由admin改为user,元素还是不会展示的,因为已经被删除了嘛,需要刷新一下页面才能显示出来,但是如果是组件式的就不会,能够灵活响应。这个一般影响不大。

    注意到我把access设置为了一个String,如果设置为一个数组也可以,iview自带的hasOneOf方法可以很好的使用

    /**
     * @param {Array} target 目标数组
     * @param {Array} arr 需要查询的数组
     * @description 判断要查询的数组是否至少有一个元素包含在目标数组中
     */
    export const hasOneOf = (targetarr, arr) => {
      return targetarr.some(_ => arr.indexOf(_) > -1)
    }

    上述内容具有一定的借鉴价值,感兴趣的朋友可以参考,希望能对大家有帮助,想要了解更多"iview权限管理怎么实现,分配权限操作是怎样"的内容,大家可以关注群英网络的其它相关文章。 群英智防CDN,智能加速解决方案
    标签: iview 权限管理

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

    猜你喜欢

    成为群英会员,开启智能安全云计算之旅

    立即注册
    专业资深工程师驻守
    7X24小时快速响应
    一站式无忧技术支持
    免费备案服务
    免费拨打  400-678-4567
    免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
    在线客服
    微信公众号
    返回顶部
    返回顶部 返回顶部
    在线客服
    在线客服