Wiidede's blog Wiidede's blog
  • 前端
  • Python
  • 算法
  • 生活
  • 其他
  • 分类
  • 标签
  • 归档
  • 关于我
  • 赞赏
  • 我的小站 (opens new window)
GitHub (opens new window)

Wiidede

小的的写前端
  • 前端
  • Python
  • 算法
  • 生活
  • 其他
  • 分类
  • 标签
  • 归档
  • 关于我
  • 赞赏
  • 我的小站 (opens new window)
GitHub (opens new window)
  • 整理一些css样式
  • vue隔代组件层层动态插槽并且附带数据
  • vue判断字符串是否溢出来显示弹窗、解决el-table tooltip 内过多导致无法显示,内容闪烁
  • 整理一些js写法
  • ElementUI timePicker 增加此刻按钮 引发的dom操作的学习
  • 毕业设计(水表识别)前端知识整理
  • html小知识
  • axios请求api然后下载文件
  • vue3+ts根据高度改变元素的透明度
  • vue3 + ElementPlus 换肤方案(Css变量)
  • Moment的一些使用方法
  • echarts基础vue组件
  • element UI el-date-picker 年月日切换组件
  • 可以不选择的el-radio单选框
  • vue的小技巧总结
  • 全局动态权限判断(Vue指令)
    • 目标
    • 实现
    • 总结
  • vue-anchor 探索
  • Deep Dive with Evan You 笔记
  • 前端基础知识查漏补缺
  • WebPack 知识总结
  • 我写的一些可以日后参考的代码
  • 接口变化后,封装接口函数,改变返回内容
  • 项目组件整理
  • 前端框架设计想发
  • 全局进度条
  • 带有token的图片vue组件:authImg,使用axios下载图片
  • 前端npm包推荐
  • 给ElInputNumber添加prefix
  • ElPagination添加页数总数
  • el-tab做成chrome类似的tab样式
  • vue-grid-layout-组件配置
  • 项目数据字典封装
  • 图表组件响应式探索
  • ElementPlus表格table列自动合并composition
  • 简单的curd组件封装
  • ElementPlus表格自定义合计列composition
  • 一些处理表格数据composition api
  • div内容溢出后,内容向左悬浮,vue组件封装
  • 文本数字溢出后,按比例缩小,vue组件封装
  • 表格使用async-validator检验composition
  • ElementPlus Form一些简单的组件整合
  • arco-design快速使用tailwind的颜色、unocss动态颜色
  • 前端
wiidede
2022-01-27

全局动态权限判断(Vue指令)

# 全局动态权限判断(Vue指令)

# 目标

在Vue组件中,使用v-has指令即可控制某一元素的权限。

后端提示权限变化的时候,前端去判断这些元素还是否有权限,并作出相应的操作。

# 实现

创建一个js文件,定义权限判断方法,以及权限判断自定义指令:

/**
 * name: v-has 动态变化
 * desc: 禁止嵌套使用v-has,不然你就自己加一下子节点的判断或者换其他方案吧
 */
import Vue from 'vue';

// 项目检查权限检查的方法,定义在Vue原型链上,方便全局调用
Vue.prototype.$_has = function (id) {
 const permission = JSON.parse(localStorage.getItem('APP_PERMISSION'));
 if (!Array.isArray(permission)) {
  return false;
 }
 return !!permission.filter(per => per.id === id).length;
};

// 收集所有需要权限判断的DOM节点
const permissionNodeConf = new Map();

// 自定义Vue指令
Vue.directive('has', {
 bind: function (el, binding) {
  const permissionKey = binding.value;
  const hasPermission = Vue.prototype.$_has(permissionKey);

  // 将Dom节点作为key,value为相应的配置
        // 为每一个Dom节点创建一个对应的注释节点
        permissionNodeConf.set(el, {
   permissionKey,
   hasPermission,
   comment: document.createComment('permission')
  });

  if (!hasPermission) {
            // 这里使用setTimeout是因为第一次绑定的时候还没有parentNode
            // 如果没有权限就将Dom节点换成注释节点
   setTimeout(() => {
    el.parentNode.replaceChild(permissionNodeConf.get(el).comment, el);
   }, 0);
  }
 },
 unbind: function (el) {
        // unbind 的时候从Map中移除相应的Dom
  permissionNodeConf.delete(el);
 }
});

export {
 permissionNodeConf
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

接下来是main.js中引用

import { permissionNodeConf } from './directive/v-has/index';

// new Vue 实例
vm = new Vue({
    el: '#app',
    // router, store, ...
});

// 初始化权限监听
Global.initPermissionWatcher(vm, permissionNodeConf);
1
2
3
4
5
6
7
8
9
10

Global.js:

global.initPermissionWatcher = function (vm, nodeMap) {
    // 监听Vuex中权限变化
 vm.$watch('$store.state.user.app_permission_change', () => {
        // 遍历收集来的Dom节点,通过对应的配置上的key判断是否有权限
  let visiblePermissionChanged = false;
  nodeMap.forEach((conf, el) => {
   const hasPermission = vm.$_has(conf.permissionKey);
   if (hasPermission !== conf.hasPermission) {
    // 权限发生变化
    // keepAlive中的也会触发,也可以使用vNode组件实例的_inactive判断判断是否在当前页面
    visiblePermissionChanged = document.contains(el) || document.contains(conf.comment);
    if (hasPermission) {
                    // 有权限,把注释节点替换回来
     conf.comment.parentNode.replaceChild(el, conf.comment);
    } else {
                    // 无权限,将Dom节点替换成注释节点
     el.parentNode.replaceChild(conf.comment, el);
    }
    conf.hasPermission = hasPermission;
   }
  });
        // 如果发现有变化的,提示页面权限变化了
  if (visiblePermissionChanged) {
   vm.$message.info('页面权限发生变化!');
  }
 });
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

接下来,你只要改变vuex中的app_permission_change的值就可以实现页面动态权限控制了。

比如后端通过websocket通知用户权限变化,这时候,重新去请求到用户权限,得到响应后,改变app_permission_change的值,即可。

# 总结

一开始我通过判断页面上是否存在Dom去删除数组中的Dom元素,但是后来我想到自定义指令还有unbind回调,就在unbind删除了元素,这样也解决了嵌套的指令使用无法使用的问题(嵌套后的子节点,不论是comment和原来的Dom节点,都不会在document上,所以会被我删除)。

还有一点,Vue页面很多会有keepAlive,这些被缓存的页面当然不会触发unbind,所以,提示用户权限变更的判断逻辑我改成了:只有document中存在的Dom并且这些Dom发生了权限变化,才会提示用户。

后来我想,能不能再binding的时候,获取到组件实例,在组件实例上监听Vuex 状态呢,然后,每个el,都会创建一个watcher?应该也是一种方法吧

#前端#Vue#自定义指令#权限判断#框架
上次更新: 2023/06/01, 12:40:50

← vue的小技巧总结 vue-anchor 探索→

Theme by Vdoing | Copyright © 2021-2023 Wiidede | Website use MIT License | Article content & logo use CC-BY-SA-4.0 License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式