1

简介

自定义指令就像一个迷你的函数,把你自定义的功能塞进这个迷你函数里,在页面上快速的调用,增加用户体验。

Vue.directive('dyColor',{
    bind:function(el){
        el.onclick = () => {
            el.style.backgroundColor = '#' + Math.random().toString().slice(2,8)
        } 
    }
})
new Vue({
    el: '#app-1'
})
<div id="app-1">
    <div class="box bg-fw" v-dy-color>
        <h1>Lorem</h1>
        <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Repellat beatae neque, quo, hic molestiae accusamus maxime cupiditate impedit quia labore aspernatur doloribus necessitatibus! Odio, quod eaque consectetur dolor asperiores id.</p>
    </div>
</div>

clipboard.png

上面这个简单示例中,使用Vue.directive('name',hooks)定义一个指令,在页面上加上前缀v-使用。
bind()为一个钩子函数,也有其他几种钩子,在钩子中完成一些自定义功能,钩子上有几个规定的参数,上面el就是一个,钩子及参数后面分析。

钩子函数

总共有五种HookbindinsertedupdatecomponentUpdatedunbind

  • bind: 在指令绑定到元素上时调用。
  • inserted: 在被绑元素插入到父节点时调用一次(父节点是否插入文档无所谓)
  • unbind: 指令与元素解绑时调用一次。

inserted是新版新加的,这个时机发生在bind之后,增加点灵活度,就目前为止没发现有什么用。

  • update:在被绑元素被修改时,修改内容未被插入时调用
  • componentUpdated: 在被绑元素被修改并把修改内容插入后调用

官网这里是外星人写的,看不清,我暂时就这么理解了,这两个也是基于老版本update修改的。把一个时间分成两部分而已。因为el引用的一个是修改前、一个是修改后的内容,还是有点用。

Vue.directive('test', {
    bind:function(el){
        el.onclick = () => {
            el.style.backgroundColor = '#' + Math.random().toString().slice(2,8)
        } 
        $(el).find('#info_update').append('<li><span class="emblem">'  + (el.parentNode?'有父元素':'无父元素') +'</span></li
        console.log(el.parentNode)
        console.log('bind')
    },
    inserted: function (el) {
        $(el).find('#info_update').append('<li><span class="emblem">'  + (el.parentNode?'有父元素':'无父元素') +'</span></li
        console.log('inserted')
    },
    update: function (el) {
        $(el).find('#info_update').append('<li><span class="emblem">'  + $(el).find('h3').text() +'</span></li>')
        console.log('update')
    },
    componentUpdated: function (el) {
        $(el).find('#info_update').append('<li><span class="emblem">'  + $(el).find('h3').text() +'</span></li>')
        console.log('componentUpdated')
    },
    unbind: function (el) {
        console.log('unbind')
    }
})
new Vue({
    el:'#app-2',
    data:function(){
        return {
            msg:'test directive',
            show:true
        }
    },
    methods:{
        updateData:function(){
            this.msg = 'hello'
        }
        
    }
})
<script>
.emblem {
    background-color: #f46;
    color: #fff;
    padding: 2px 4px;
    font-size: 14px;
    line-height: 15px;
    height: 15px;
    border-radius: 4px;
    margin-top:5px;
    display: inline-block;
}
</script>
<div id="app-2">
    <button @click="updateData" class="btn btn-warn btn-sm">update</button>
    <button @click="show = !show" class="btn btn-warn btn-sm">bind&Insert</button>
    <button @click="show = !show" class="btn btn-warn btn-sm">unbind</button>
    <div class="box" v-if="show" v-test>
        <h3>{{msg}}</h3>
        <p id="info_update">
        </p>
        <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Reprehenderit ad aut cupiditate.</p>
    </div>
</div>

clipboard.png

插入被绑元素时,可以看到bind阶段的被绑元素没有父元素,而inserted阶段是有的;而update阶段使用的是修改前的数据,componentUpdated阶段是使用后的数据,点击解绑按钮就是移除被绑元素,自然指令也和元素解绑了。

钩子函数参数

因为这几个参数,直接导致Vue灵活度*2,就像定义一个组件那样,自定义指令因为参数的开放性会有无限种可能。

  • el:指令所绑定的元素,可以用来直接操作DOM
  • binding:一个对象,包含与指令本身相关的一些属性:

    • name:指令名,不包括v-前缀
    • value:指令的绑定值,如例v-hello = "1 + 1"中,绑定值为2
    • expression:字符串形式的指令表达式。例如v-hello = "1 + 1"中,表达式为"1 + 1"
    • oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用,无论值是否改变都可用
    • arg:传给指令的参数,可选。例如v-hello:message中,参数为"message"
    • modifiers:一个包含修饰符的对象。例如v-hello.foo.bar中,修饰符对象为{foo:true, bar:true}
  • vnode:Vue编译生成的虚拟节点。可以看成el的底层表现,我们就可以通过它进一步去操作被绑元素
  • oldVnode: 修改前的VNODE,仅在update和componentUpdated两个钩子函数中可用

一个有意义的示例不可能覆盖它们,在这里只能做个观察,后面写插件时尽量使用它们。


yanniecheung
70 声望6 粉丝