精读 Vue 官方文档系列 🎉
简介
Vue 指令可以分为”内置指令(例如:v-once,v-cloak等)“与“自定义指令“。 Vue 指令提供了操作底层 DOM 的能力,增强了 Vue 模板的处理功能。
- 局部注册指令,可以使用组件选项
directives。 - 全局注册指令,需要调用 Vue 构造函数的
Vue.directive()方法
钩子函数
“指令”的构成与组件选项类似,有着自己独特的钩子函数。
bind: 只调用一次,当指令与元素进行绑定时调用,此时可以对元素进行初始化操作(比如事件的绑定)。inserted: 被绑定元素插入父节点时调用(但不能保证父节点本身已经插入到文档中)。update: 组件更新之前调用。componentUpdated: 组件更新之后调用。unbind: 只调用一次,当指令与元素解绑时调用,例如v-if控制的组件。
bind 与 inserted 区别
| bind | inserted |
|---|---|
| 是在元素(Vdom)被创建后并与指令进行绑定时调用。 | 元素与指令绑定完成,并被插入到父节点时调用。 |
触发时元素没有插入到父节点中,所以 el.parentNode 返回为 null。 | 调用在 bind 之后,此时元素已经插入到父节点中,所以 el.parentNode 可以正确返回父节点的引用。 |
是在 DOM 树绘制之前调用,因而获取不到有关元素渲染的信息。 | 函数是在 DOM 树绘制之后调用,因而可以获取到有关元素渲染的信息。 |
Vue.directive('dom',{
bind(el){
console.log(el.offsetWidth); //0
console.log(el.parentNode); //null
},
inserted(el){
console.log(el.offsetWidth); //1170
console.log(el.parentNode); //<div msg="Welcome to Your Vue.js App"><button>click</button><div>false</div></div>
}
})
update 与 componentUpdated 差异
它们的区别更像是 beforeUpdate 与 updated。
<button @click="show = !show">click</button>
<div v-dom>{{ show }}</div>
此时,点击按钮切换响应式数据 show 的值为 true,观察自定义指令的输出:
Vue.directive("dom", {
update(el) {
console.log("update", el.innerHTML); //'update false'
},
componentUpdated(el) {
console.log("componentUpdated", el.innerHTML); //'componentUpdated true'
},
});
自定义指令钩子中没有 Vue 实例,
this默认指向undefined。
钩子函数参数
完整的指令结构:
<span v-directiveName:argument.modifier="show"></span>
是否很抽象,那么代入实际例子去理解:
<button v-on:mousemove.passive="doSomeThing"></button>
Vue 指令的钩子方法会接收以下四个参数:
el: 当前指令所绑定的元素。binding: 指令本身的信息,值为一个对象。name: 指令的名称。rawName: 完整原始名称,含v-*前缀。value: 指令的值。expression: 指令的表达式。arg: 传给指令的参数,支持动态参数。modifiers: 指令的修饰符。oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
vnode: Vue 编译生成的虚拟节点。oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
value 与 expression 的联系
Vue 指令被调用时可以接收一个符合 JavaScript 规定的字符串形式的“表达式”的值(核心就是指令的值)。而 value 则是 expression 执行最终计算后的值。
v-calc="1 + 1"
//expression "1+1"
//value 2;
常见的表达式,例如原始表达式、算术表达式、对象和数组的初始化表达式、调用表达式等。
| expression | value |
|---|---|
| "true" | true |
| "1" | 1 |
| "'hello'" | "hello" |
| "show"(响应式变量) | false |
| "{x: 2.3, y: -1.2}" | {x: 2.3, y: -1.2} |
| "1 + 2" | 3 |
| "(v)=>{}" | ƒ (v) |
动态指令参数
指令的参数可以是动态的。例如,在 v-dom:[argument]="value" 中,argument 参数可以根据组件实例的响应式数据进行更新,这使得自定义指令可以在应用中被灵活使用。
Vue.directive("dom", {
bind(el, binding) {
if (binding.arg === "color") {
el.style.color = binding.value;
} else if (binding.arg === "background") {
el.style.background = binding.value;
}
},
});
使用指令的方式:
<div v-dom:background="'red'">{{ show }}</div>
<div v-dom:color="'green'">{{ show }}</div>
返回已注册的指令
Vue.directive('directiveName');