基于 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 的 createdunbind 对应 unmounted),需注意语法差异
  • 实际项目中,hasPermission 的判断逻辑需替换为真实的权限校验(如从全局状态或接口获取权限信息)
  • 无权限时的提示逻辑可根据业务需求调整(如使用 UI 库的消息提示组件替代 console.log
posted @ 2023-02-12 23:10  天渺工作室  阅读(702)  评论(0)    收藏  举报