• Vue(九) 自定义指令


    前面介绍了许多 Vue 内置的指令,比如 v-if、v-show等,这些丰富的指令能满足我们绝大部分的业务需求,不过在需要一些特殊功能时,我们仍然希望对 DOM 进行底层的操作,这时就要用到自定义指令。

    基本用法

    自定义指令的注册方法和组件很像,也分全局注册和局部注册,比如注册一个 v-focus 的指令,用于在 <input>、<textarea> 元素初始化时自动获取焦点,两种写法分别是:

    //全局注册
    Vue.directive('focus', {
        //指令选项
    });
    
    // 局部注册
    var app = new Vue({
        el: '#app',
        directives: {
            focus: {
               	//指令选项
            }
        }
    })
    

    上面只是注册了自定义指令 v-focus,还没有实现具体功能,下面具体介绍自定义指令的各个选项。

    自定义指令的选项是由几个钩子函数组成的,每个都是可选的。

    • bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时只执行一次的初始化操作。
    • inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
    • update:被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值可以忽略不必要的模板更新。
    • componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
    • unbind:只调用一次,指令与元素解绑时调用。

    可以根据需求在不同的钩子函数内完成逻辑代码,例如上面的 v-focus,我们希望在元素插入父节点时就调用,那用到的最好是 inserted。例如:

    <div id="app">
            <input type="text" v-focus>
        </div>
        <script>
            Vue.directive('focus', {
                inserted: function (el) {
                    el.focus();
                }
            })
    
            var app = new Vue({
                el: '#app'
            })
        </script>
    

    每个钩子函数都有几个参数可选,比如上面我们用到了 el。它们的含义如下:

    • el:指令所绑定的元素,可以用来直接操作 DOM。
    • binding:一个对象,包含以下属性:
      • name:指令名,不包括 v- 前缀。
      • value:指令的绑定值,例如 v-my-directive=“1 + 1”,value 的值是2。
      • oldValue:指令绑定的前一个值,仅在 update 和 componentupdated 钩子中可用。无论值是否改变都可以。
      • expression:绑定值的字符串形式,例如 v-my-directive=“1 + 1”,expression 的值是“1 + 1”。
      • arg:传给指令的参数。例如 v-my-directive: foo,arg 的值是 foo。
      • modifiers:一个包含修饰符的对象。例如 v-my-directive.foo.bar,修饰符对象 modifiers 的值是 { foo: true, bar: true }。
    • vnode:Vue编译生成的虚拟节点,在进阶中介绍。
    • oldVnode:上一个虚拟节点仅在 update 和 componentupdated 钩子中可用。

    下面是结合了以上参数的一个具体样例,代码如下:

       <div id="app">
            <div v-test:msg.a.b="message"></div>
        </div>
        <script>
            Vue.directive('test', {
                bind: function (el, binding, vnode) {
                    var keys = [];
                    for(var i in vnode) {
                        keys.push(i);
                    }
                    el.innerHTML = 
                        'name:' + binding.name + '<br>' +
                        'value:' + binding.value + '<br>' +
                        'expression:' + binding.expression + '<br>' +
                        'argument:' + binding.arg + '<br>' +
                        'modifiers:' + JSON.stringify(binding.modifiers) + '<br>' +
                        'vnode keys:' + keys.join(',')
                }
            })
    
            var app = new Vue({
                el: '#app',
                data: {
                    message: 'some text'
                }
            })
        </script>
    

    执行后结果为:

    name:test
    value:some text
    expression:message
    argument:msg
    modifiers:{"a":true,"b":true}
    vnode keys:tag,data,children,text,elm,ns,context,fnContext,fnOptions,fnScopeId,key,componentOptions,componentInstance,parent,raw,isStatic,isRootInsert,isComment,isCloned,isOnce,asyncFactory,asyncMeta,isAsyncPlaceholder

    在大多数场景,我们会在 bind 钩子里绑定一些事件,比如在 document 上用 addEventListrener 绑定,在unbind 里用 removeEventListener 解绑,比较典型的示例就是让这个元素随着鼠标拖拽。

    如果需要多个值,自定义指令也可以传入一个 JavaScript 对象字面量,只要是合法类型的 JavaScript 表达式都是可以的。例如:

       <div id="app">
            <div v-test="{msg: 'hello', name: 'jj'}"></div>
        </div>
        <script>
            Vue.directive('test', {
                bind: function (el, binding, vnode) {
                    console.log(binding.value.msg);
                    console.log(binding.value.name);
                }
            })
    
            var app = new Vue({
                el: '#app',
            })
        </script>
    
    作者:kindleheart
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    2019/1/2
    2018/12/22
    2018/12/18
    2018/12/17
    2018/12/16
    编程总结汇总
    学习总结汇总
    第十三周学习总结--助教
    第十一周编程总结
    第10周编程总结
  • 原文地址:https://www.cnblogs.com/kindleheart/p/10009564.html
Copyright © 2020-2023  润新知