Vue 3 自定义指令:用 directive 封装权限控制与按钮防抖
test12026-09-140 次阅读
指令的本质
Vue 的指令是“带副作用的 DOM 行为封装”。和组件解决“渲染什么”不同,指令解决“这个 DOM 元素挂载后要做点什么”——权限裁剪、事件节流、自动聚焦都是它的典型舞台。复用逻辑时,指令比混入组件模板更轻。
权限指令 v-permission
把“用户是否拥有某权限”的判断收敛进一个指令,模板里只写权限点,没权限的按钮直接不渲染,避免在每个页面手写判断。
import type { Directive, DirectiveBinding } from "vue";
// 假设登录后把权限数组挂到全局
function getUserPermissions(): string[] {
return (window as any).__permissions ?? [];
}
export const permission: Directive<HTMLElement, string | string[]> = {
mounted(el, binding: DirectiveBinding<string | string[]>) {
const required = Array.isArray(binding.value)
? binding.value
: [binding.value];
const owned = getUserPermissions();
const ok = required.every((p) => owned.includes(p));
if (!ok) {
el.parentNode?.removeChild(el);
}
},
};
防重复点击指令 v-debounce-click
提交类按钮最怕用户连点导致重复请求。用一个捕获阶段的 click 指令,在锁定期间吞掉后续点击,比在每个 handler 里手写锁更省心。
import type { Directive } from "vue";
export const debounceClick: Directive<HTMLButtonElement, number> = {
mounted(el, binding) {
const wait = binding.value || 500;
let lock = false;
const handler = (e: Event) => {
if (lock) {
e.stopImmediatePropagation();
e.preventDefault();
return;
}
lock = true;
setTimeout(() => {
lock = false;
}, wait);
};
el.addEventListener("click", handler, true);
(el as any).__handler = handler;
},
unmounted(el) {
el.removeEventListener("click", (el as any).__handler, true);
},
};
全局注册
import { createApp } from "vue";
import App from "./App.vue";
import { permission } from "./directives/permission";
import { debounceClick } from "./directives/debounceClick";
const app = createApp(App);
app.directive("permission", permission);
app.directive("debounce-click", debounceClick);
app.mount("#app");
在模板里使用
<template>
<button v-permission="'order:delete'" @click="remove">删除订单</button>
<button v-debounce-click="800" @click="submit">提交</button>
</template>
经验清单
- 指令适合“横切”多个元素的通用行为;单一业务的逻辑还是放在组件里更清楚。
- 需要随响应式数据变化而更新的行为,用 updated 钩子,而不只是 mounted。
- 指令里挂到 el 上的私有字段(如上例 __handler)要在 unmounted 里清理,避免内存泄漏。
- 权限相关的指令只做“展示层裁剪”,服务端仍必须做真正的鉴权。
T
test1
文章作者
指令的本质 Vue 的指令是“带副作用的 DOM 行为封装”。和组件解决“渲染什么”不同,指令解决“这个 DOM 元素...
- 分类
- 技术
- 发布时间
- 2026-09-14
- 字数
- 约 2322 字
- 阅读
- 0 次
