首页  >  文章  >  web前端  >  Vue自定义指令及指令定义函数的具体分析(代码)

Vue自定义指令及指令定义函数的具体分析(代码)

不言
不言原创
2018-07-21 16:09:362022浏览

Vue自定义指令可以在全局或局部定义,Vue组件是html和代码的复用,而Vue指令是对DOM的扩展复用;下面我们就来具体看看对Vue中自定义指令的分析。

1、Vue自定义指令:使用Vue.directive(id,definition)注册全局自定义指令,使用组件的directives选项注册局部自定义指令。

2、Vue 钩子函数:

指令定义函数提供了几个钩子函数(可选):

bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。

inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。

update:第一次是紧跟在 bind 之后调用,获得的参数是绑定的初始值,之后被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。

componentUpdated:被绑定元素所在模板完成一次更新周期时调用。

unbind:只调用一次, 指令与元素解绑时调用。

3、Vue 钩子函数的参数:(el, binding, vnode, oldVnode)

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.a.b,modifiers的值为{'a':true,'b':true}

vnode:Vue编译的生成虚拟节点;

oldVnode:上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。

<p id="app" v-demo:foo.a.b="message"></p>

Vue.directive(&#39;demo&#39;, {
  bind: function (el, binding, vnode) {
      console.log(&#39;bind&#39;);
    var s = JSON.stringify
    el.innerHTML =
      &#39;name: &#39;       + s(binding.name) + &#39;<br>&#39; +
      &#39;value: &#39;      + s(binding.value) + &#39;<br>&#39; +
      &#39;expression: &#39; + s(binding.expression) + &#39;<br>&#39; +
      &#39;argument: &#39;   + s(binding.arg) + &#39;<br>&#39; +
      &#39;modifiers: &#39;  + s(binding.modifiers) + &#39;<br>&#39; +
      &#39;vnode keys: &#39; + Object.keys(vnode).join(&#39;, &#39;)
  }
});
new Vue({
  el: &#39;#app&#39;,
  data: {
    message: &#39;hello!&#39;
  }
});

 4、函数简写:大多数情况下,我们可能想在 bind 和 update 钩子上做重复动作,并且不想关心其它的钩子函数。可以这样写:

Vue.directive(&#39;color-swatch&#39;, function (el, binding) {
  el.style.backgroundColor = binding.value
})

5、对象字面量:如果指令需要多个值,可以传入一个 JavaScript 对象字面量。记住,指令函数能够接受所有合法类型的 Javascript 表达式。 

<p v-demo="{ color: &#39;white&#39;, text: &#39;hello!&#39; }"></p>

Vue.directive(&#39;demo&#39;, function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "hello!"
})

 例子解析:

<p id="app">
    <my-comp v-if="msg" :msg="msg"></my-comp>
    <button @click="update">更新</button>
    <button @click="uninstall">卸载</button>
    <button @click="install">安装</button>
</p>
<script type="text/javascript">
    Vue.directive(&#39;hello&#39;, {
        bind: function (el){
            console.log(&#39;bind&#39;);
        },
        inserted: function (el){
            console.log(&#39;inserted&#39;);
        },
        update: function (el){
            console.log(&#39;update&#39;);
        },
        componentUpdated: function (el){
            console.log(&#39;componentUpdated&#39;);
        },
        unbind: function (el){
            console.log(&#39;unbind&#39;);
        }
    });

    var myComp = {
        template: &#39;<h1 v-hello>{{msg}}</h1>&#39;,
        props: {
            msg: String
        }
    }

    new Vue({
        el: &#39;#app&#39;,
        data: {
            msg: &#39;Hello&#39;
        },
        components: {
            myComp: myComp
        },
        methods: {
            update: function (){
                this.msg = &#39;Hi&#39;;
            },
            uninstall: function (){
                this.msg = &#39;&#39;;
            },
            install: function (){
                this.msg = &#39;Hello&#39;;
            }
        }
    })
</script>

a、页面加载时:bind inserted

b、更新组件:update componentUpdated

c、卸载组件:unbind

d、重新安装组件:bind inserted

注意区别:bind与inserted:bind时父节点为null,inserted时父节点存在;update与componentUpdated:update是数据更新前,componentUpdated是数据更新后。

6.最后上一个实际开发的指令封装实现

基本思路

import store from &#39;@/store&#39;

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const roles = store.state.permission.pagePermission
    if (value && typeof value === &#39;string&#39; && value.length > 0) {
      const hasPermission = roles.some(role => {
        return role.permission == value
      })
      if (!hasPermission) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    } else {
      throw new Error(`need roles! Like v-permission="&#39;button&#39;"`)
    }
  }
}

 向外暴露api

import permission from &#39;./permission&#39;

const install = function(Vue) {
  Vue.directive(&#39;permission&#39;, permission)
}

if (window.Vue) {
  window[&#39;permission&#39;] = permission
  Vue.use(install) // eslint-disable-line
}

permission.install = install
export default permission

相关推荐:

vue自定义指令实现v-tap插件

怎样使用Vue的自定义指令完成一个下拉菜单

以上是Vue自定义指令及指令定义函数的具体分析(代码)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn