Vue之自定义指令

1. Vue自定义指令的简述

Vue除了提供了默认内置的指令外,还允许开发人员根据实际情况自定义指令,它的作用价值在于当开发人员在某些场景下需要对普通DOM元素进行操作的时候。

2. Vue自定义指令的划分

Vue自定义指令可以划分为全局指令局部指令
注意:指令本质就是操作我们当前的DOM节点,不管是内置指令还是自定义指令,都是操作DOM节点的。

3. 如何注册自定义指令

在上面第二点提到了Vue自定义指令可以划分为全局指令以及局部指令。
我们首先来看看注册全局指令的方式,如我们去main.js文件中写入:Vue.directive(自定义指令名称,配置项);
接下来我们再来看看局部指令的方式,如我们去App.vue文件中写入:

1
2
3
4
5
6
7
8
export default{
directives:{
// 在这里local-highlight是自定义指令名称
'local-highlight':{
// 配置项
}
}
}

注意:要去使用这个指令的话,需要在前面加上v-。如全局指令中Vue.directive(‘highlight’,{});如果要使用该指令的话,应该写为:v-highlight;如局部指令中应该写为:v-local-highlight

4. 钩子函数

一个指令定义对象可以提供如下几个钩子函数,均为可选。
全局指令中写入钩子函数:

  1. bind()钩子函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Vue.directive('highlight',{
    // 当我们去绑定这个指令的话,它就会触发这个钩子函数,
    // 需要注意的是:只能触发一次
    bind(el,binding,vnode){
    // el表示原生DOM节点
    // binding表示绑定指令的时候传的一些参数(只读)
    // vnode表示虚拟DOM节点(只读)
    }
    });
    我们来举一个例子:
    App.vue文件中写入:
    1
    2
    3
    4
    5
    <template>
    <div class="container">
    <p v-highlight="'yellow'">我是自定义的p标签</p>
    </div>
    </template>
    在main.js文件中写入:
    1
    2
    3
    4
    5
    6
    7
    8
    Vue.config.productionTip = false
    Vue.directive('highlight',{
    bind(el,binding,vnode){
    console.log(el); // <p>我是自定义的p标签</p>
    console.log(binding); // {name: "highlight", rawName: "v-highlight", value: "yellow" …}
    console.log(vnode); // VNode {tag: "p", data: {…}, children: Array(1), text: undefined, elm: p, …}
    }
    });
  2. update()钩子函数
    1
    2
    3
    4
    5
    6
    7
    8
    Vue.directive('highlight',{
    // 当前这个节点有一定更新了,就会触发这个钩子函数
    update(el,binding,vnode,oldvnode){
    // el,binding和前面bind()钩子函数中介绍的一样
    // vnode表示现在虚拟DOM是什么样子的
    // oldvnode表示以前的节点长什么样子的
    }
    });
    我们来举一个例子:
    在App.vue中写入:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <template>
    <div class="container">
    <button v-highlight="'yellow'" @click="btnClick">{{ myData }}</button>
    </div>
    </template>
    <script>
    export default {
    data(){
    return {
    myData: '我是自定义的button标签'
    }
    },
    methods:{
    btnClick(){
    this.myData = '我是改变之后的button标签';
    }
    }
    }
    </script>
    在main.js文件中写入:
    1
    2
    3
    4
    5
    6
    7
    8
    Vue.directive('highlight',{
    update(el,binding,vnode,oldvnode){
    console.log(el); // <button>我是改变之后的button标签</button>
    console.log(binding); // {name: "highlight", rawName: "v-highlight", value: "yellow", expression: "'yellow'"…}
    console.log(vnode); // VNode {tag: "button", data: {…}, children: Array(1), text: undefined, elm: button, …}
    console.log(oldvnode); // VNode {tag: "button", data: {…}, children: Array(1), text: undefined, elm: button, …}
    }
    });
  3. inserted()钩子函数
    1
    2
    3
    4
    5
    6
    7
    Vue.directive('highlight',{
    // 当我们插入到当前这个DOM的时候,它才会触发这个钩子函数
    // 需要注意一点:这个函数只触发一次
    inserted(el,binding,vnode){
    // el,binding,vnode和前面bind()钩子函数中介绍的一样
    }
    });
    我们来举一个例子:
    在App.vue中写入:
    1
    2
    3
    4
    5
    <template>
    <div class="container">
    <button ref="myBtn" v-highlight="'yellow'">我是自定义的button标签</button>
    </div>
    </template>
    在main.js文件中写入:
    1
    2
    3
    4
    5
    6
    7
    Vue.directive('highlight',{
    inserted(el,binding,vnode){
    console.log(el); // <button>我是自定义的button标签</button>
    console.log(binding); // {name: "highlight", rawName: "v-highlight", value: "yellow", expression: "'yellow'" …}
    console.log(vnode); // VNode {tag: "button", data: {…}, children: Array(1), text: undefined, elm: button, …}
    }
    });
    从这里我们会发现绑定钩子函数和插入钩子函数很相似,但是它们之间是有区别的:…写的是一些模板,模板要通过编译的过程,再向正常的html中插入。我们在模板中去绑定的时候,就监测到这个指令了,而编译完成之后,往当前html中插入的时候触发inserted()钩子函数。
  4. componentUpdated()钩子函数
    1
    2
    3
    4
    5
    6
    Vue.directive('highlight',{
    // 当我们完成更新的时候会触发这个函数
    componentUpdated(el,binding,vnode,oldvnode){
    // el、binding、vnode、oldvnode与update()钩子函数中的解析一样
    }
    });
  5. unbind()钩子函数
    1
    2
    3
    4
    5
    6
    Vue.directive('highlight',{
    // 当我们解绑这个指令的时候,就会触发这个钩子函数
    unbind(el,binding,vnode){
    // el、binding、vnode与前面的bind()钩子函数的解析一样
    }
    });
    局部指令与全局指令类似,在这里我只举一个例子来说明一下钩子函数在局部指令中如何使用。
    我们在App.vue中写入:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <template>
    <div class="container">
    <p v-highlight="'green'">我是局部自定义的p标签</p>
    </div>
    </template>
    <script>
    export default{
    directives: {
    'local-highlight': { // 局部指令的名字
    bind(el,binding,vnode){}
    }
    }
    }
    </script>