跳到主要内容

Vue3自定义指令

· 阅读需 3 分钟
ppnnssy
Nobody

官方说:只有当所需功能只能通过直接的 DOM 操作来实现时,才应该使用自定义指令。
上一个项目中使用了自定义指令控制按钮权限,这里写一下自定义指令的用法。

创建设置按钮权限的自定义指令

/**
* v-auth
* 按钮权限指令
*/

import type { Directive, DirectiveBinding } from "vue";

const auth: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
const { value } = binding;
console.log(value);

const currentPageRoles = ["add", "delete"]
if (value instanceof Array && value.length) {
const hasPermission = value.every(item => currentPageRoles.includes(item));
if (!hasPermission) el.remove();
} else {
if (!currentPageRoles.includes(value)) el.remove();
}
}
};

export default auth;

上面的代码非常简单,就是创建了一个对象,在里面定义了mounted钩子函数。通过钩子函数对el,即使用此指令的元素进行操作。
函数的参数可以参考官方文档: https://cn.vuejs.org/guide/reusability/custom-directives#introduction

全局挂载

在main.ts中全局挂载自定义指令

import auth from '@/directives/index.ts'

const app = createApp(App)
app.directive("auth", auth)

组件内挂载

组件内挂载只需要引入的时候把对象名命名为v开头的驼峰命名即可。

import vAuth from '@/directives/index.ts'

使用

  <button @click="handleClick" v-auth="'add'">点我</button>
<button @click="cancel" v-auth="'cancel'">取消</button>

这样,第一个按钮就能显示,第二个就隐藏了。

其他的细节操作,都可以在钩子函数中完成

多个自定义指令全局挂载

当然可以都导入到main.ts中,然后挨个挂载。但是这样main.ts未免太长。最好封装个函数,挨个挂载。

import { App, Directive } from "vue";
import auth from "./modules/auth";
import copy from "./modules/copy";
import waterMarker from "./modules/waterMarker";
import draggable from "./modules/draggable";
import debounce from "./modules/debounce";
import throttle from "./modules/throttle";
import longpress from "./modules/longpress";

const directivesList: { [key: string]: Directive } = {
auth,
copy,
waterMarker,
draggable,
debounce,
throttle,
longpress
};

const directives = {
// install函数会在app挂载插件的时候执行
install: function (app: App<Element>) {
Object.keys(directivesList).forEach(key => {
// 在app上挨个挂载自定义指令
app.directive(key, directivesList[key]);
});
}
};

export default directives;

这里的做法是导入所有指令,然后做成一个插件,在main.ts中全局挂载。

import directives from "@/directives/index";
// ...
app.use(ElementPlus).use(directives).use(router).use(I18n).use(pinia).mount("#app");

或者也可以不使用插件,用比较简单的方法,直接弄个函数:

import type { App } from "vue";
import auth from "./auth";

const serDirectives = (app: App) => {
app.directive("auth", auth);
// 有多个自定义指令的话就继续挂载其他指令...
}

export default serDirectives;

然后在main.ts中直接调用:

import serDirectives from "@/directives/index.ts"

const app = createApp(App)
serDirectives(app)

这样也可以实现多个自定义指令的挂载。