基于 Vue 自定义指令实现点击事件权限控制
在许多业务场景中,需要对按钮等元素的点击事件添加权限校验:当用户拥有权限时,正常触发点击事件;无权限时,则拦截事件或执行其他提示逻辑。若通过封装组件实现,在使用第三方 UI 库(如 Element Plus)的场景下,会导致封装成本过高。本文将介绍如何通过 Vue 自定义指令低成本实现这一需求。
适用场景
- 需要对点击事件进行权限拦截的业务场景
- 基于第三方 UI 库开发,希望避免大量组件封装
- Vue2/Vue3 均适用(语法稍有差异,本文以 Vue3 为例)
解决方案实现
1. 全局注册自定义指令(main.ts)
通过全局自定义指令封装权限校验逻辑,无需修改现有组件结构,直接在元素上通过指令使用。
// main.ts
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router/router";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
const app = createApp(App);
app.use(router);
app.use(ElementPlus);
// 注册全局自定义指令 v-permission
app.directive("permission", {
// 元素创建时绑定事件
created(el, binding) {
// 生成事件处理函数并保存到 el 的自定义属性中(避免污染全局)
const handleClick = () => {
// 实际场景中替换为真实的权限判断逻辑
const hasPermission = true;
if (hasPermission) {
// 有权限:执行原点击事件
binding.value();
} else {
// 无权限:拦截事件并执行提示逻辑(如弹窗提示)
console.log("无权限操作,已拦截点击事件");
// 可补充:ElMessage.warning('您没有操作权限')
}
};
// 保存函数引用到 el 上(关键:确保移除时能找到同一个函数)
el._clickHandler = handleClick;
// 绑定事件
el.addEventListener("click", handleClick);
},
// 元素卸载时移除事件监听(避免内存泄漏)
unmounted(el) {
// 从 el 上获取之前保存的函数引用
const handleClick = el._clickHandler;
if (handleClick) {
// 移除事件(引用一致,确保能正确销毁)
el.removeEventListener("click", handleClick);
// 清除保存的引用,释放内存
delete el._clickHandler;
}
},
});
app.mount("#app");
2. 在页面中使用指令
无论是原生按钮还是第三方 UI 组件(如 Element Plus 的 el-button),均可直接通过 v-permission 指令绑定点击事件,支持带参数和不带参数的两种调用方式。
预览
<template>
<!-- 1. 不带参数的点击事件 -->
<button v-permission="handleClick">原生按钮(无参数)</button>
<el-button type="primary" v-permission="handlePrimaryClick">
Element 按钮(无参数)
</el-button>
<!-- 2. 带参数的点击事件(通过箭头函数传递参数) -->
<button v-permission="() => handleClickWithParams('test')">
原生按钮(带参数)
</button>
<el-button type="success" v-permission="() => handleSuccessClick(100, '示例')">
Element 按钮(带参数)
</el-button>
</template>
<script lang="ts" setup>
// 无参数的点击事件处理函数
const handleClick = () => {
console.log("原生按钮点击(无参数)");
};
const handlePrimaryClick = () => {
console.log("Element 按钮点击(无参数)");
};
// 带参数的点击事件处理函数
const handleClickWithParams = (str: string) => {
console.log("原生按钮点击(带参数):", str);
};
const handleSuccessClick = (num: number, str: string) => {
console.log("Element 按钮点击(带参数):", num, str);
};
</script>
注意事项
- Vue2 中自定义指令的钩子名称不同(如
bind对应 Vue3 的created,unbind对应unmounted),需注意语法差异 - 实际项目中,
hasPermission的判断逻辑需替换为真实的权限校验(如从全局状态或接口获取权限信息) - 无权限时的提示逻辑可根据业务需求调整(如使用 UI 库的消息提示组件替代
console.log)

浙公网安备 33010602011771号