Vue 权限管理DOM显示和隐藏(方法 和 directive)

438 阅读3分钟
  • 使用函数判断是否存在在使用if判断显示与否

1.登录时获取权限列表

当我们登录时需要获取token,过期时间(expires_at),用户信息(user_info)这些东西。
那么当我们需要实现权限管理功能的时候我们可以把权限列表(permissions=['接口一','接口二'])也通过登录接口拿回来

2.存放接口在vuex中,并可以持久化存于localStorage中

这一步是为了我们需要使用到权限列表的时候全局都需要使用

问题一、何时清理这个vuex中localStorage跟对应的permissions呢?

当我们退出登录时或响应拦截器拦截到响应回来的状态码为固定值时,我们执行退出方法,退出方法里面进行vuex与localStrage中permission的清除,具体可以这样写

logout(state) {
    state.permissions = null;
    localStorage.removeItem("permissions");
}

问题二、那么有人说我们刷新vuex中的数据不是就消失了,这个问题该如何解决呢?

我们都知道localStorage具有持久化储存的作用,那么我们可以使用它来达到持久化存储。

以下我们给到一种方案,是基于localStorage实现的一种vuex数据持久化插件,当我们刷新时,vuex中的数据可以不消失,并且可以指定谁不消失,关键代码实现如下,vuex-persistedstate具体使用方法可以自行百度。

import createPersistedState from "vuex-persistedstate";
new Vuex.Store({
    plugins: [
        createPersistedState({
            reducer(data) {
                return {
                    token: data.token,
                    permissions: data.permissions,
                };
            },
        }),
    ],
    state: {
        permissions: null, // 跟vuex的方法同理不变
    },

当我们没有用此段代码来实现permissions数据持久化时刷新可以看到permissions自动消失了,如下图

image.png 重新登录,当我们使用上面的一段代码刷新之后如下图,刷新之后任然还在

image.png

3.封装一个方法,将其挂载到原型上,其目的是用来过滤权限的

main.js 关键实现代码如下:

const getPermission = (part, user) => {
        console.log(part) // {"user-add":false,"user-edit":false}
        console.log(user) // product_basic_view,product_basic_line-add
	part = Object.keys(part);
	user = user.split(",");
	let permission = {};
	part.forEach((item) => {
		let index = user.indexOf(item);
		let bool = index >= 0 ? true : false;
		permission[item] = bool;
	});
	return permission;
};
Vue.prototype.$permission = (u) => {
    return getPermission(u, store.state.permissions)
};

4.系统中有个文件专门用来对应权限的管理

和后端商量好的格式名称一般是json文件 根据key在需要的页面在data中定义参照# 5

此文件结构如下:

{
    "key": "user-add",
    "name": "系统管理_人员管理_新增人员",
    "api": [
        "/api/system/user/create"
    ]
},
{
    "key": "user-edit",
    "name": "系统管理_人员管理_编辑人员",
    "api": [
        "/api/system/user/update",
        "/api/system/user/switch_status",
        "/api/system/user/reset_password"
    ]
}

5.在某个模块中调用这个方法实现权限过滤

我界面上有一些按钮,这些按钮会实现相应的操作,那么这些操作需要根据权限来屏蔽

某个界面中的data中有如下数据,在某个界面需要用到对应权限屏蔽某个dom的,或者某个操作不能做的,根据接口列表来做一个bool值的判断

permission: {
    "user-add":false,
    "user-edit":false
},

需要使用的组件中的created生命周期里面过滤权限

created() {
    this.permission = this.$permission(this.permission)
    console.log("this.permission",this.permission);
}
复制代码

打印出来就拿到了我们的权限

6.利用过滤出来的权限来实现相应不同权限的效果

在上一步我们已经实现了将对应的权限过滤成bool值
那么我们就可以用if来屏蔽dom,或者在方法中根据bool值来阻止操作example:

<div class="flex flex-align-c" v-if="permission['user-edit']">
    <a class="link margin-r-10" title="编辑" @click="openModal('edit', select.level, select)">
    <a-icon type="edit" />
</div>
  • 使用directive实现权限

创建AUTH_MAPPER对象里面的键值对中的值代表权限者的id,可以通过键值对来判断当前登陆者的身份显示一些功能与否。
如果是页面可以后端处理好之后返回菜单接口数据 或者前端在路由router处理(前者安全系数最高)

const AUTH_MAPPER = {
  "FZ-FZ-XZ": [1, 2, 11, 32, 91, 88, 89], //服装-新增
  "DJ-DJ-XZ": [1, 2, 11, 32, 91, 88, 89], //道具-新增
  "FZ-FZ-PLDR": [1, 2, 11, 32, 91, 88, 89], //服装-批量导入
  "ZYGL-YY-BJ-INTB": [1, 2, 11, 32, 91, 88, 86], //资源管理-演员-编辑
  "CD-CDK-ZL-INTB": [1, 2, 11, 32, 91, 88, 87, "SELF"], //场地-租赁
};

在main.js 中创建directive 对象中的inserted函数表示当绑定了该指令的元素被插入到dom时候会自动触发
inserted包含三个参数 el val vnode 打印如下

image.png

Vue.directive("auth", {
  inserted: function (el, val, vnode) {
    console.log(el);
    console.log(val);
    console.log(vnode);
    if (!val) el.style.display = "none";
    let { value } = val;
    if (!AUTH_MAPPER[value]) return (el.style.display = "none");
    // Number(store.getters.currentRoleId) // 利用接口获取用户的信息的roleId 
    // 是否存在AUTH_MAPPER中的键值对中的值
    // 如果存在intb
    if (value.indexOf("INTB") != -1) {
      if (AUTH_MAPPER[value].includes(Number(4))) {
        console.log("执行1");
        return;
      } else if (AUTH_MAPPER[value].includes("SELF")) {
        console.log("执行2");
        // let rowdata = vnode.data.attrs.rowdata || {};
        let rowdata = {};
        let create_user_id =
          rowdata.order_create_user_id || rowdata.create_user_id;
        if (Number(1) == Number(create_user_id)) {
          console.log("执行3");
          return;
        } else {
          console.log("执行4 - 按钮不可点击改变为灰色",);
          el.classList.add("is-disabled");
          el.disabled = true;
        }
      } else {
        console.log("执行5");
        el.classList.add("is-disabled");
        el.disabled = true;
      }
    } else {
      console.log("执行6");
      if (AUTH_MAPPER[value].includes(Number(1))) {
        el.style.display = "";
        console.log("执行7");
      } else {
        el.style.display = "none";
      }
    }
  },
});

在vue页面使用时

<div v-auth="'FZ-FZ-XZ'">你的身份是否能让你看见该标签</div>