自定义指令(详细完整版)
2026年1月21日 14:53
一、自定义指令的生命周期钩子
| 钩子函数 | 促发时机 | 常用参数 |
|---|---|---|
| created | 绑定元素属性/事件监听器应用前触发 | el, binding, vnode |
| beforeMount | 元素被挂载到DOM前触发 | el, binding, vnode |
| mounted | 元素被挂载到DOM后触发 | el, binding, vnode |
| beforeUpdate | 组件更新前触发 | el, binding, vnode, prevVnode |
| updated | 组件更新后触发 | el, binding, vnode, prevVnode |
| beforeUnmount | 元素从DOM中卸载前触发 | el, binding, vnode |
| unmounted | 元素从DOM中卸载后触发 | el, binding, vnode |
二、钩子参数
el : 指令绑定的真实DOM
binding : 一个对象,包含以下属性
value : 传递给指令的值
oldValue : 之前的值,仅在 beforeUpdate 和 updated 中可用
arg : 传递给指令的参数,例如:v-directive:test中,参数为test
modifiers : 一个包含修饰符的对象,例如:v-directive.foo.bar,那么修饰符对象为{foo:true,bar:true}
instance : 使用指令的当前组件实例
vnode : 绑定元素的底层VNode
prevVnode : 之前渲染中指令绑定的元素VNode,仅在 beforeUpdate 和 updated 中可用
三、局部自定义指令
例如:让input输入框聚焦
<template>
<div>
<input v-focus="true" />
</div>
</template>
<script setup lang="ts">
const vFocus = {
mounted(el, binding) {
if (binding.value === true) el.focus();
},
};
</script>
任何以v开头的驼峰式命名的变量都可以当作自定义指令使用,例如vFocus在模板中以v-focus的形式使用
四、全局自定义指令
import { createApp } from "vue";
const app = createApp(App);
app.directive("focus", {
mounted(el, binding) {
if (binding.value === true) el.focus();
},
});
五、简化形式(函数式指令)
当仅需要在mounted和updated上实现相同的行为,不需要使用到其他钩子函数时,可以直接用一个函数来定义指令
import { createApp } from "vue";
const app = createApp(App);
app.directive("focus", (el, binding) => {
if (binding.value === true) el.focus();
});
六、实战
自定义权限控制指令
第一步:我们定义一个权限数组,代表当前登陆人有的所有权限(实际项目中一般从后端获取)
const userPermissions = ["add", "delete", "reset"];
第二步:自定义全局的权限控制的指令
const hasPermission = (needPermissions: string | string[]) => {
//无权限要求时,默认显示
if (!needPermissions) return true;
//将传入的权限标识统一转为数组处理
const needPerms = Array.isArray(needPermissions)
? needPermissions
: [needPermissions];
//传入的权限标识必须全部拥有才为true
return needPerms.every((perm) => userPermissions.includes(perm));
};
app.directive("permission", (el, binding) => {
const isShow = hasPermission(binding.value);
if (!isShow && el) el.remove();
});
第三步:在需要权限控制的页面使用自定义指令控制权限
<template>
<div v-permission="'add'">新增</div>
<div v-permission="'delete'">删除</div>
<div v-permission="'reset'">修改</div>
<div v-permission="'find'">查找</div>
<div v-permission="['add', 'delete']">新增和删除</div>
<div v-permission="['reset', 'find']">修改和查找</div>
</template>
最后,验证结果如下
![]()