自定义指令 directive
Vue 中所有的指令,在调用的时候,都以 v- 开头。除了内置的指令( 如 v-if ),Vue 也允许注册自定义指令。
在 Vue2.0 中,代码复用和抽象的主要形式是组件,
然而,有些情况下,仍然需要对普通 DOM 元素进行底层操作,这时,就会用到自定义指令。
语法规则
定义一个自定义指令,主要有两种方式:全局注册( 如,按钮级权限 )和局部注册。其结构如下:
- 指令名称:顾名思义,“指令的名称”,可自主命名。
在定义的时候,指令名称的前面不需要加 v- 前缀;而,在调用的时候,必须在指令名称前加上 v- 进行调用。
- 自定义对象:该对象身上,有一些指令相关的钩子函数,这些函数可以在特定的阶段,执行相关的操作
- 钩子函数 & 参数
动态指令参数
<template>
<div class="content">
<input type="text" v-focus v-bgColor="{ bgCol }" />
</div>
</template>
<script>
import Vue from "vue";
// 定义方式1:全局注册
Vue.directive("focus", {
// 指令名称 & 自定义指令对象
inserted: function (el) {
// 钩子函数 & 参数
el.focus(); // 获取元素焦点
},
});
export default {
data() {
return {
bgCol: "red",
};
},
// 定义方式 2:局部注册(使用directives选项)
directives: {
// 指令名称
bgColor: {
// 自定义指令对象
inserted: function (el, binding) {
// 钩子函数 & 参数
el.style.backgroundColor = binding.value.bgCol; // 改变元素的背景色
},
},
},
};
</script>
理解:钩子函数和参数
一个自定义指令对象,可以提供如下钩子函数( 均为可选 ):
- bind:只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置
- inserted:被绑定元素插入父节点时调用( 仅保证父节点存在,但不一定已被插入到文档中 )
- update:所有组件的 VNode 更新时调用,但可能发生在其子 VNode 更新之前。指令的值,可能发生了变化,也可能没有。可以结合相关参数比较更新前后的值来忽略不必要的模板更新
- componentUpdated:指令所在的组件的 VNode 及其子 VNode 全部更新后调用
- unbind:只调用一次,指令与元素解绑时调用
Vue.directive("focus", { bind: function (el) { // 元素刚绑定指令的时候,还没有插入到DOM中去,这个时候调用focus方法无效,因为一个元素只有插入DOM后才能获取焦点 // el.focus(); // 时机不对 }, inserted: function (el) { // 表示元素插入到DOM中的时候,会执行inserted函数(触发一次) el.focus(); }, updated: function () { // 当VNode更新的时候,会执行updated,可能会触发多次 } });
钩子函数,可以传入以下参数( 需说明的是,除 el 外,其他参数都应该是只读的,切勿修改 ):
- el:指令所绑定的元素,可以用来直接操作 DOM,是指令钩子函数的第一个参数。
- binding:第二个参数,是一个对象。主要包括以下属性:
- name:指令名称( 不包括 v- 前缀 )如,binding.name,结果为 'bgColor'
- value:指令绑定的值。如,binding.value.bgCol,结果为 'red'
- oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 中可用
- expression:字符串形式的指令表达式,如 v-my-directive="1+1",binding.value.express,结果为 '1+1'
- arg:传给指令的参数,可选。如 v-my-directive:foo 中,参数为 'foo'
- modifers:一个包含修饰符的对象。如 v-my-directive.foo.bar 中,修饰符为 { foo: true, bar: true }
- vnode:Vue 编译生成的虚拟节点( 移步 VNode API,了解更多 )
- oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用