关于前端:Vuex自定义指令实现按钮粒度的权限控制

42次阅读

共计 2923 个字符,预计需要花费 8 分钟才能阅读完成。

如何在 vue 我的项目中通过后端的权限数据对组件中的按钮、元素进行显示暗藏?(如管理员能看到所有按钮 非管理员只能应用某些按钮),咱们在登入时通过接口取得如下用户的菜单数据,包含每个菜单中有 opFlag:1 代表以后此节点为菜单,否则 opFlag:2 代表以后用户的这个菜单下能够显示(有权限应用)的按钮:
菜单树数据(含按钮):

{
    "id": 932,
    "opName": "业务管理",
    "opFlag": 1,
    "url": "/BusinessManagement",
    "icon": "#iconscx",
    "btnList": "","children": [ {"id": 1041,"opName":" 客户治理 ","opFlag": 1,"url":"/CustomerManagement","icon":"",
        "children": [{
            "id": 1160,
            "opName": "删除",
            "opFlag": 2,
            "url": "del",
            "icon": "","children": []},{
            "id": 1161,
            "opName": "编辑",
            "opFlag": 2,
            "url": "edit",
            "icon": "","children": []}]
    }, {
        "id": 933,
        "opFlag": 1,
        "url": "/userManagement",
        "icon": "","children": [{"id": 934,"opName":" 用户列表 ","opFlag": 1,"url":"",
            "icon": "","children": [{"id": 937,"opName":" 申请账号 ","opFlag": 1,"url":"/userManagement/apply","icon":"",
                "children": []},  ]
        }, ]
    }]
}

这里咱们不须要关注 opFlag:1 的菜单数据,只关注 opFlag:2 的按钮数据。
通过以上现有的按钮数据,在 vuex 中定义键值形式的权限表。通过 mutations 把对应菜单的按钮权限数组项一一 push 到 vuex 中:
store.js

  state: {"/userManagement": [], // 用户模块权限
    "/CustomerManagement": [] // 客户模块},
  mutations: {setAuthList(state, auth) {state[auth.name].push(auth.authList);
    },
}

state 中对应的键值 "url":["权限 1","权限 2"]

接下来须要拆散出按钮数据,operations为菜单树数据:

if(operations && operations.length > 0 && operations[0].children) {_this.menuData =   this.filterMenuData(operations[0].children);
          
}else {_this.menuData = [];
}


setBtnListStore(url,auth){
     // 以按钮所属父级模块的 url 为模块名设置到 vuex 中,要在 vuex 中当时定义对应模块
    if(this.$store.state[url]){this.$store.commit('setAuthList',{name:url,authList:auth});
     }             
 },


filterMenuData(data){ // 过滤出不含按钮的菜单数据
            let _that = this;
            let menuData = (function deepCopy( source,pUrl) {let target = [] 
                for (var k in source) {if (source.hasOwnProperty(k)) {if ( typeof source[ k] === 'object') {if( Array.isArray(source)){ // 以后在 cildren 当中 递归深拷贝 json 
                               if(source[ k].opFlag == 1){ // 菜单,如果是菜单才进行下一步的深拷贝
                                   target[k] = deepCopy(source[ k] ,source.url)
                               }else{// 按钮
                                if(pUrl){_that.setBtnListStore(pUrl,source[k].url); // 设置到 vuex 中
                                }
                               }
                           }else{target[ k] = deepCopy(source[ k],source.url )
                           }
                        } else {target[ k] = source[k]
                        }
                     }
                }
                return target
            })(data)
           return menuData;
},

咱们获取了树形的菜单数据后对菜单进行渲染同时通过 filterMenuData 过滤到 opFlag:2 的数据,而后通过 setBtnListStore 把菜单和对应的按钮列表存储入 vuex 中。
operations 菜单数据操作前先深拷贝一次,免得影响原有数据,在拷贝递归的同时获取按钮权限信息。

接下来就是撸一个 vue 自定义指令,创立authVueDirective.js 用于在 vue 中创立自定义指令 auth:


import Vue from 'vue';
let authList = []
let setAuthList = (list)=>{ 
  // 在组件中传入以后用户的权限列表
authList = list||[];}
const hasPermission = userPermission => {
  // 以后用户的权限列表
  return authList.some(i => userPermission.includes(i));
};
// 权限指令
Vue.directive("auth", {inserted: (el, binding, vnode) => {if (!hasPermission(binding.value)) {el.parentNode.removeChild(el);
    }
  }
});
export default {setAuthList}

authList是一个用于存储权限的列表,在 v-auth="['xxx']" 应用时,判断 v-auth 所需的权限是否存在于 authList 列表中,否则不存在示意以后无权限则移除元素(按钮),到这里咱们就实现了整个按钮权限的所需工作,接下来看看如何在组件中应用它:

/CustomerManagement 页面中引入 authVueDirective.js 存储以后页面的权限列表(伪代码):

template:<el-button  @click="del"
v-auth="['del']"> 删除 </el-button>
  <el-button  @click="add"
v-auth="['add']"> 增加 </el-button>

import vauth from '@/assets/js/authVueDirective.js';

created(){
   // 设置按钮权限
   vauth.setAuthList(this.$store.state['/CustomerManagement']);
   // 这里的 setAuthList 相当于 vauth.setAuthList(['del','edit']);
},

最终删除按钮在因为咱们有 del 能显示进去,增加按钮则不能显示。

正文完
 0