在 Vue 2 中,自定义指令通过 Vue.directive()
方法或组件选项的 directives
对象定义
一、全局自定义指令
通过 Vue.directive()
全局注册,所有组件可用:
// main.js 或全局入口文件
import Vue from 'vue';
// 注册全局指令 'my-directive'
Vue.directive('my-directive', {
// 指令的生命周期钩子
bind(el, binding, vnode) {
console.log('指令首次绑定到元素时调用', el);
},
inserted(el, binding, vnode) {
console.log('元素插入父节点时调用', el);
},
update(el, binding, vnode, oldVnode) {
console.log('组件更新时调用(可能发生在子组件更新之前)', el);
},
componentUpdated(el, binding, vnode, oldVnode) {
console.log('组件及子组件全部更新后调用', el);
},
unbind(el, binding, vnode) {
console.log('指令与元素解绑时调用', el);
}
});
使用方式:
<div v-my-directive="someValue"></div>
二、局部自定义指令
在组件选项中通过 directives
定义,仅当前组件可用:
export default {
directives: {
'my-directive': {
bind(el, binding) {
// 指令逻辑
el.style.color = binding.value;
}
}
},
data() {
return { color: 'red' };
}
}
模板中使用:
<p v-my-directive="color">这段文字会变成红色</p>
三、指令钩子函数详解
每个指令可包含以下钩子(均为可选):
钩子名称 | 调用时机 | 参数说明 |
---|---|---|
bind | 指令第一次绑定到元素时调用(一次性初始化设置) | el : 指令绑定的元素binding : 包含指令信息的对象vnode : Vue 虚拟节点 |
inserted | 绑定元素插入父节点时调用(不保证已被渲染) | 同上 |
update | 所在组件更新时调用(可能发生在子组件更新前) | 新增 oldVnode 参数 |
componentUpdated | 所在组件及子组件全部更新后调用 | 同上 |
unbind | 指令与元素解绑时调用(清理工作) | 同 bind |
四、binding
对象属性
钩子函数的 binding
参数包含以下属性:
属性 | 说明 |
---|---|
name | 指令名(不含 v- 前缀) |
value | 指令绑定的值(如 v-my-dir="1 + 1" 的 value 为 2 ) |
oldValue | 指令绑定的前一个值(仅在 update 和 componentUpdated 中可用) |
expression | 字符串形式的绑定表达式(如 v-my-dir="1 + 1" 的 expression 为 "1 + 1" ) |
arg | 指令参数(如 v-my-dir:arg 的 arg 为 "arg" ) |
modifiers | 包含修饰符的对象(如 v-my-dir.mod1.mod2 的 modifiers 为 { mod1: true, mod2: true } ) |
五、实用示例
1. 自动聚焦输入框
Vue.directive('focus', {
inserted(el) {
el.focus();
}
});
<input v-focus>
2. 权限控制指令
Vue.directive('permission', {
inserted(el, binding) {
if (!checkPermission(binding.value)) {
el.parentNode.removeChild(el);
}
}
});
<button v-permission="'admin'">仅管理员可见</button>
3. 拖拽指令
Vue.directive('drag', {
bind(el) {
el.onmousedown = (e) => {
const disX = e.clientX - el.offsetLeft;
const disY = e.clientY - el.offsetTop;
document.onmousemove = (e) => {
el.style.left = e.clientX - disX + 'px';
el.style.top = e.clientY - disY + 'px';
};
document.onmouseup = () => {
document.onmousemove = null;
};
};
}
});
<div v-drag style="position: absolute">拖拽我</div>
七、注意事项
-
避免滥用:优先使用组件和 props 解决需求,指令适合 DOM 操作相关功能。
-
样式处理:在
bind
或inserted
中修改样式,避免在update
中重复操作。 -
内存泄漏:在
unbind
中移除事件监听器和定时器。
通过自定义指令,你可以直接操作 DOM 并复用常见行为,从而增强 Vue 的灵活性。