RBAC前端架构-07:自定义指令role、permission实现权限控制

1-自定义指令

1-1.概念

Vue2 允许开发者通过自定义指令来操作 DOM 元素。自定义指令分为两种:

  • 全局指令:在整个应用中都可以使用
  • 局部指令:仅在特定组件中生效

1-2.自定义指令的生命周期钩子

  • bind:指令第一次绑定到元素时调用,只触发一次
  • inserted:被绑定元素插入父节点时调用
  • update:所在组件的 VNode 更新时调用
  • componentUpdated:所在组件的 VNode 及其子 VNode 全部更新后调用
  • unbind:指令与元素解绑时调用

1-3.示例

js 复制代码
// 定义全局自定义指令 v-show-if
Vue.directive('show-if', {
  bind(el, binding) {
    // binding.value 是指令传入的值
    el.style.display = binding.value ? '' : 'none';
  },
  update(el, binding) {
    // 数据更新时重新判断
    el.style.display = binding.value ? '' : 'none';
  }
});

// 使用方式
<template>
  <div v-show-if="isVisible">Hello World</div>
</template>

<script>
export default {
  data() {
    return {
      isVisible: true // 控制显示/隐藏
    };
  }
};
</script>

2-文件调整

新增frontend-vue2\src\directives\permission.js

作用:

  1. 提供了两个自定义指令:v-permission 和 v-role,用于根据用户的权限或角色动态控制 DOM 元素的显示与隐藏
  2. 生命周期钩子:bind:首次绑定到元素时执行一次权限检查、update:当模板重新解析(数据更新)时再次执行权限检查
  3. 通过 setupPermissionDirective(Vue) 方法将两个指令注册为全局指令
js 复制代码
import store from "@/store";

// 自定义权限指令,定义bind和update生命周期钩子
export const permission = {
  // bind:只调用一次,指令第一次绑定到元素时调用。在这里进行一次权限检查
  // 参数一:el:令所绑定的DOM元素
  // 参数二:binding:指令对象,对象中包含指令的相关信息
  bind(el, binding) {
    checkPermission(el, binding);
  },
  // update:指令所在的模版被重新解析时调用(数据更新)
  update(el, binding) {
    checkPermission(el, binding);
  },
};

// 自定义权限指令,定义bind和update生命周期钩子
export const role = {
  bind(el, binding) {
    checkRole(el, binding);
  },
  update(el, binding) {
    checkRole(el, binding);
  },
};

// 权限检查函数
function checkPermission(el, binding) {
  const { value } = binding;
  console.log("权限检查" + value);
  if (value) {
    const hasPermission = store.getters["user/hasPermission"](value);
    console.log("权限检查结果:" + hasPermission);
    if (!hasPermission) {
      // 使用 display 控制隐藏指令修饰el
      el.style.display = hasPermission ? "" : "none";
      // 从 DOM 中直接移除
      // el.parentNode && el.parentNode.removeChild(el);
    }
  }
}

// 角色检查函数
function checkRole(el, binding) {
  const { value } = binding;

  if (value) {
    const hasRole = store.getters["user/hasRole"](value);
    // el.style.display = hasRole ? "" : "none";
    if (!hasRole) {
      // 使用 display 控制隐藏指令修饰el
      el.style.display = hasRole ? "" : "none";
      // 从 DOM 中直接移除
      // el.parentNode && el.parentNode.removeChild(el);
    }
  }
}

// 传入vue,然后注册自定义指令(Vue2)
export default function setupPermissionDirective(Vue) {
  // 添加全局指令v-permission:细粒度控制权限,功能级别控制
  Vue.directive("permission", permission);
  // 添加全局指令v-role
  Vue.directive("role", role);
}

修改frontend-vue2\src\main.js

js 复制代码
import Vue from "vue";
import App from "./App.vue";
// 路由组件
import router from "./router";
// Vuex
import store from "./store";
// 引入 Element UI
import ElementUI from "element-ui";
// 引入 Element UI 的样式
import "element-ui/lib/theme-chalk/index.css";
// Element UI 的样式之后可以再次引入自定义样式,对默认的Element UI 的样式覆盖
//import xxxx.css
// 引入自定义权限指令
import setupPermissionDirective from "@/directives/permission";

// 使用 Element UI
Vue.use(ElementUI);

// 将指令注册到 Vue 实例上
setupPermissionDirective(Vue);

Vue.config.productionTip = false;

new Vue({
    router,
    store, // 把 store 注入全局
    render: (h) => h(App),
}).$mount("#app");

后续使用:

html 复制代码
<!-- 权限控制 -->
<el-button v-permission="'user:create'">创建用户</el-button>
<!-- 角色控制 -->
<el-button v-role="'ADMIN'">管理员功能</el-button>
相关推荐
echome8885 小时前
Python 异常处理:try、else、finally 的正确搭配
开发语言·前端·python·异常处理·编程技巧
时间的情敌6 小时前
OpenLayers 实战|Vue3 + OpenLayers 完整工程案例(加载天地图、要素、弹窗、绘制、WFS)
前端·openlayers
陈随易6 小时前
下载神器!Motrix 停更三年后重写回归
前端·后端·程序员
前端的日常6 小时前
一个人+AI做情侣食谱小程序,0 费用的服务器
前端·后端
计算机魔术师7 小时前
谷歌搜索广告踩刹车,AI广告成为救命稻草
前端
总要学点什么7 小时前
第81篇:数据可视化-PM2.5分布——让圆点的胖瘦替每座城市报出浓度
前端·信息可视化·echarts·cesium·空间分析
IT_陈寒7 小时前
Vue的v-for里用了个临时变量,页面直接挂了
前端·人工智能·后端
hunter_0767 小时前
一次 iOS 真机签名 409 的完整排查:证书、设备、描述文件为什么总是"对不上"
前端
枣把儿7 小时前
开源!公众号排版+一键发布工具懒人版
前端
2501_916007477 小时前
抓包工具功能对比,TraceEagle、Charles、Fiddler、Wireshark、mitmproxy 差别
前端·网络协议·ios·adb·https·fiddler·wireshark