Vue自定义指令-按钮权限

先看看官方怎么说:

一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数:Vue自定义指令文档链接

和组件类似,自定义指令在模板中使用前必须先注册。
1.使用 directives 选项完成了指令的局部注册

export default {
  directives: {
    // 在模板中启用 v-focus
    focus
  }
}

2.将一个自定义指令全局注册到应用层级

const app = createApp({})
// 使 v-focus 在所有组件中都可用
app.directive('focus', {
		  /* ... */
})

指令函数

const myDirective = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
    // 下面会介绍各个参数的细节
  },
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

钩子函数

在 Vue.js 的自定义指令中,常用的钩子函数有以下几种:

//bind 钩子函数

bind: function(el, binding, vnode) {
  // 指令第一次绑定到元素时被调用
}

//bind 钩子函数只会在指令第一次被绑定到元素时执行一次,适合用于初始化指令的行为,比如为元素绑定事件、添加 class 等操作。其中,el 参数是指令所绑定的元素,binding 参数是一个对象,包含了指令的绑定信息,vnode 参数是 Vue.js 中虚拟 DOM 的节点。

//inserted 钩子函数

inserted: function(el, binding, vnode) {
  // 指令所绑定的元素被插入到父节点时被调用
}

//inserted 钩子函数会在指令所绑定的元素被插入到父节点时被调用,适合用于操作 DOM 结构的行为,比如添加元素、设置样式等操作。其中,参数的含义和 bind 钩子函数相同。

//update 钩子函数

update: function(el, binding, vnode, oldVnode) {
  // 指令所绑定的元素的值发生改变时被调用,但子节点的变化不会触发该函数
}

//update 钩子函数会在指令所绑定的元素的值发生改变时被调用,但不包括子节点的变化,适合用于修改元素的属性或样式等操作。其中,oldVnode 是钩子函数的一个新参数,在新旧节点差异更新时非常有用。

//componentUpdated 钩子函数

componentUpdated: function(el, binding, vnode) {
  // 指令所绑定的元素的值或子节点发生改变时被调用
}

//componentUpdated 钩子函数会在指令所绑定的元素的值或子节点发生改变时被调用,适合用于动态修改元素的属性和样式。其中,参数的含义同 inserted 和 update 钩子函数。

//unbind 钩子函数

unbind: function(el, binding, vnode) {
  // 指令与元素解绑时被调用
}


//unbind 钩子函数只会在指令与元素解绑时被调用,适合用于清理元素的操作,比如移除事件监听、移除 DOM 元素等操作。其中,参数的含义同 bind 钩子函数。
//以上是常用的自定义指令钩子函数,可以根据需求选择使用。在钩子函数中可以直接操作 DOM 元素、绑定事件、设置样式等,但需要注意性能问题,尽量避免长时间占用主线程。同时,也要注意使用 vnode 与虚拟 DOM 结构进行交互时会影响组件的性能。

钩子参数说明

  • el:指令绑定到的元素。这可以用于直接操作 DOM。
  • binding:一个对象,包含以下属性。
    • value:传递给指令的值。例如在 v-my-directive=“1 + 1” 中,值是 2。
    • oldValue:之前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否更改,它都可用。
    • arg:传递给指令的参数 (如果有的话)。例如在 v-my-directive:foo 中,参数是 “foo”。
    • modifiers:一个包含修饰符的对象 (如果有的话)。例如在 v-my-directive.foo.bar 中,修饰符对象是 { foo: true, bar: true }。
    • instance:使用该指令的组件实例。
    • dir:指令的定义对象。
  • vnode:代表绑定元素的底层 VNode。
  • prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在 beforeUpdate 和 updated 钩子中可用

tip:除了 el 外,其他参数都是只读的,不要更改它们。

敲重点,自定义指令实现-按钮控制

import { useUserStoreHook } from '@/store/modules/user';
import { Directive, DirectiveBinding } from 'vue';
/**
 * 按钮权限
 */
 
export const hasPerm: Directive = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    // 「超级管理员」拥有所有的按钮权限
    const { roles, perms } = useUserStoreHook();
    if (roles.includes('ROOT')) {
      return true;
    }
    // 「其他角色」按钮权限校验
    const { value } = binding;
    if (value) {
      const requiredPerms = value; // DOM绑定需要的按钮权限标识
      //具体功能是将有权限的权限项转化为布尔值,判断是否有必要权限。其中 perms 和 requiredPerms 都是数组,分别存放用户具有的权限和所需权限。这里使用 some 方法遍历 perms 数组,如果其中有一个元素requiredPerms 数组中出现过,则返回 true,表示具有必要权限,否则返回 false,表示缺少必要权限。?. 运算符是可选链运算符,它可以在调用对象属性或方法时防止因为对象不存在导致的异常错误。在这里,perms 和 perms 数组都可能是 undefined 或 null,使用 ?. 防止了这种情况下的错误。
      const hasPerm = perms?.some(perm => {
        return requiredPerms.includes(perm);
      });
      //权限判断元素是否需要在页面上显示,如果没有所需权限,则将元素从页面上移除
      if (!hasPerm) {
        el.parentNode && el.parentNode.removeChild(el);
      }
    } else {
      throw new Error(
        "need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
      );
    }
  }
};

指令注册

import { hasPerm } from './permission';

// 全局注册 directive 方法
export function setupDirective(app: App<Element>) {
  // 使 v-hasPerm 在所有组件中都可用
  app.directive('hasPerm', hasPerm);
}
import { setupDirective } from '@/directive';

const app = createApp(App);
// 全局注册 自定义指令(directive)
setupDirective(app);

指令具体使用

<el-button v-hasPerm="['sys:user:add']">新增</el-button>
<el-button v-hasPerm="['sys:user:delete']">删除</el-button>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值