开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
上一篇我们介绍过vue里面的内置指令,但是很多时候时候内置指令不能满足我们的需求开发,因此vue给我们提供了自定义指令的配置项,这样我们就可以根据需求自定义指令,自定义的指令在模板中的用法和内置指令是一样的。
定义自定义指令
1. 全局指令和局部指令
自定义指令和过滤器一样,按照作用域来划分也分为两种:全局指令和局部指令
定义全局指令
Vue.directive(指令名,配置对象)
或者
Vue.directive(指令名,回调函数)
定义局部指令
directives: {
指令名: 配置对象
}
或者
directives() {
}
2. 函数式自定义指令和对象式自定义指令
自定义指令可以按照两种方式去配置:函数式和对象式
函数式自定义指令
函数式指令就是将指令定义成回调函数,这样在触发的时候就会触发回调函数,回调函数包含两个参数:el和binding。
基本写法
<template>
<div class="test-wrapper">
<div v-test>自定义指令</div>
</div>
</template>
<script>
export default {
data () {
return {
};
},
directives: {
test(el, binding) {
console.log('el', el);
console.log('binding', binding);
}
}
};
根据打印信息,我们可以看到el表示dom元素,binding表示包含元素有关的所有属性的对象
传递参数
指令也是可以传递参数的
<template>
<div class="test-wrapper">
<div v-test="number">自定义指令</div>
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
</div>
</template>
<script>
export default {
data () {
return {
number: 1
};
},
directives: {
test(el, binding) {
console.log('el', el);
console.log('binding', binding);
}
},
methods: {
addNumber() {
this.number++;
}
}
};
</script>
参数binding的value属性可以拿到传递过来的参数。效果如下:
如果这个参数被组件中别的部分修改了,那么指令也会被执行,而且能拿到最新的值。比如增加number的值,参数也变了。效果如下:
对象式自定义指令
对象式也就是在指定定义对象中添加几个钩子函数,这些钩子都是可选的。
- bind: 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
- inserted: 被绑定元素插入父节点时调用(仅保证父节点存在,但不一定被插入文中)
- update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生变化也有可能没有。
- componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用
- unbind: 只调用一次,指令与元素解绑时调用
这些钩子函数具有以下参数:
- el: 指令所绑定的元素,可以用来直接操作DOM
- binding: 一个包含元素属性的对象
- vnode: Vue编译生成的虚拟节点
- oldVnode: 上一个虚拟节点,仅在update和componentUpdated钩子中使用
<template>
<div class="test-wrapper">
<div>number的值: {{number}}</div>
<button @click="addNumber">增加number</button>
<input type="text" v-test="number">
</div>
</template>
<script>
export default {
data () {
return {
number: 1
};
},
directives: {
test: {
bind(el, binding) {
el.value = binding.value;
},
inserted(el, binding) {
el.focus();
},
update(el, binding) {
el.value = binding.value;
}
}
},
methods: {
addNumber() {
this.number++;
}
}
};
</script>
初始化的时候,会执行bind和inserted,效果如下:
改变number的值,会执行update,效果如下:
小结
- 函数式定义指令相当于是简写版,只会在初始化和模板变化(解析)的时候被触发,而对象式可以根据钩子函数在特定的时候执行对应的操作
- 指令定义的时候不加v-, 但使用时要加v-
- 指令名如果时多个单词,要使用kebab-case命名方式,不要用驼峰命名。