欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

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

程序员文章站 2022-03-26 16:05:21
...

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

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

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

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

<p v-demo="{ color: 'white', text: 'hello!' }"></p>

Vue.directive('demo', 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('hello', {
        bind: function (el){
            console.log('bind');
        },
        inserted: function (el){
            console.log('inserted');
        },
        update: function (el){
            console.log('update');
        },
        componentUpdated: function (el){
            console.log('componentUpdated');
        },
        unbind: function (el){
            console.log('unbind');
        }
    });

    var myComp = {
        template: '<h1 v-hello>{{msg}}</h1>',
        props: {
            msg: String
        }
    }

    new Vue({
        el: '#app',
        data: {
            msg: 'Hello'
        },
        components: {
            myComp: myComp
        },
        methods: {
            update: function (){
                this.msg = 'Hi';
            },
            uninstall: function (){
                this.msg = '';
            },
            install: function (){
                this.msg = 'Hello';
            }
        }
    })
</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 '@/store'

export default {
  inserted(el, binding, vnode) {
    const { value } = binding
    const roles = store.state.permission.pagePermission
    if (value && typeof value === 'string' && 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="'button'"`)
    }
  }
}

向外暴露api

import permission from './permission'

const install = function(Vue) {
  Vue.directive('permission', permission)
}

if (window.Vue) {
  window['permission'] = permission
  Vue.use(install) // eslint-disable-line
}

permission.install = install
export default permission

相关推荐:

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

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

以上就是Vue自定义指令及指令定义函数的具体分析(代码)的详细内容,更多请关注其它相关文章!

相关标签: Vue自定义指令