Vue中directive自定义指令


 

想必大家在使用Vue的时候,会经常用的Vue的一些指令。

比如v-modelv-onv-bindv-ifv-else-ifv-forv-showv-slot等。

那么,大家有没有遇到这些指令不能满足需求的时候,自己尝试自定义指令呢?

我们今天就跟大家一起学习一下,如何写一个简单的指令!


什么是指令?

指令是带有前缀v-以表示它们是vue提供的特殊的属性。

指令的作用,可以理解是写在DOM元素上的属性,而这个属性具有它特定的职责。

当表达式的值改变的时候,会产生一定的响应行为,而这些响应行为会作用在绑定的DOM元素上。

什么是自定义指令?

除了核心的功能默认内置的指令v-model和v-show,Vue允许注册自定义指令。

Vue中代码复用的主要形式和抽象是组件,但是有的情况下,仍需对底层的DOM进行操作,这时候就可以使用自定义指令。

自定义指令的生命周期(钩子函数)

  • bind

只会在初始化时候调用一次,用于当前指令第一次绑定到元素时候调用

  • inserted

被绑定的元素插入到父亲节点时候调用

  • update

指令所在组件的Vnode数据更新的时候调用,但是有可能并不会发生改变,这个时候,可以通过使用钩子参数更新前后的值来区分不必要的模版更新

  • componentUpdated

指令所在组件的Vnode和其子Vnode全部更新后调用

  • unbind

指令和元素解绑的时候调用,一般是Dom中删除绑定指令的元素时就会调用

先看一下demo

<template>
  <div class="hello">
    <h1>局部测试生命周期test</h1>
    <p v-my-local-hook="msg">{{ msg }}</p>
  </div>
</template>
<script>
//测试生命周期test
export default {
  name: 'HookDirective',
  props: {
    msg: String
  },
  directives:{
    myLocalHook:{
      bind(){
        //首次绑定dom,相当于第一次初始化
        console.log('bind 首次绑定dom,相当于第一次初始化')
      },
      inserted(){
        //被绑定元素插入到父节点时候调用
        console.log('inserted 被绑定元素插入到父节点时候调用')
      },
      update(){
        console.log('update 数据更新的时候')
      },
      componentUpdated(){
        console.log('componentUpdated 指令所在组件的Vnode及其子Vnode全部更新后调用')
      },
      unbind(){
        console.log('unbind 只调用用一次,就是当指令与元素解绑时候调用')
      }
    }
  }
}
</script>




然后我们看一下打印结果,可以更清晰看到其执行顺序,一般常用到的是bindupdate

生病周期(钩子函数)的参数

我们以自定义局部指令为例,打印内容顺序分别是el、binding、vnode

  • el 指令绑定的元素,可以用来直接操作DOM

  • binding 返回的是一个对象,值分别是

    • name  指令的名称,不包括v-

    • value 通过指令传入的值

    • oldValue 通过指令传入的上一次的值,仅在updatecomponentUpdated钩子中又返回值。

    • expression 字符串类型的指令表达式。

      如图v-my-local="{color:colorLocal,fontSize:fontSizeLocal}"

      表达式即color:colorLocal,fontSize:fontSizeLocal"

    • arg 传给指令的参数,如图v-my-local:argFoo,其参数为argFoo

    • modifiers 一个包含修饰符的对象,如图v-my-local:argFoo.modifiersTest,其对象为{modifiersTest:true}

arg与modifiers的区别在于一个是使用:一个是使用.

  • vnode Vue编译生成的虚拟节点

  • oldVnode Vue编译生成的上一个虚拟节点,仅在updatecomponentUpdated钩子中返回值。

多个参数传值(对象字面量字面量)

如果指令需要多个值,可以传入一个 JavaScript 对象字面量。

记住,指令函数能够接受所有合法的 JavaScript 表达式。

实例

自定义全局指令

(关键在于Vue.directive())

第一步在main.js中写入我们的全局指令

import Vue from 'vue'
import App from './App.vue'


Vue.config.productionTip = false


Vue.directive('myGlobal',{
  bind(el,binding,vnode) {
        //首次绑定dom,相当于第一次初始化
        console.log(el,binding,vnode)
        el.style.color=binding.value.color
        el.style.fontSize=binding.value.fontSize+'px'
      },
      update(el, binding, vnode) {
       //首次绑定dom,相当于第一次初始化
        console.log(el,binding,vnode)
        el.style.color=binding.value.color
        el.style.fontSize=binding.value.fontSize+'px'
      }
})
new Vue({
  render: h => h(App),
}).$mount('#app')


第二步即可使用,我们以==app.vue==文件和==globalDirective.vue==文件为例

app.vue

<template>
  <div id="app">
   <div>
      <HookDirective v-if="updateMsg" :msg="updateMsg"/>
      <input v-model="updateMsg" type="text">
   </div>
   <div>
      <localDirective :color-local="colorLocal" :font-size-local="fontSizeLocal"/>
      <label for="fontColor1">文本颜色</label>
      <input type="text" v-model="colorLocal" name="fontColor1">
      <br>
      <br>
      <label for="fontSize1">文字大小</label>
      <input type="number" v-model="fontSizeLocal"  name="fontSize1" id="">
   </div>
   <div>
      <globalDirective :color-global="colorGlobal" :font-size-global="fontSizeGlobal"/>
      <label for="fontColor2">文本颜色</label>
      <input type="text" v-model="colorGlobal" name="fontColor2">
      <br>
      <br>
      <label for="fontSize2">文字大小</label>
      <input type="number" v-model="fontSizeGlobal"  name="fontSize2" id="">
      <p v-my-global="{color:'red',fontSize:'22'}">我在主页面使用了全局指令,成功了耶~</p>
   </div>
  </div>
</template>


<script>
import HookDirective from './components/HookDirective.vue'
import localDirective from './components/localDirective.vue'
import globalDirective from './components/globalDirective.vue'


export default {
  name: 'App',
  components: {
    HookDirective,
    localDirective,
    globalDirective
  },
  data(){
    return{
      updateMsg:'测试生命周期',
      colorLocal:'red',
      fontSizeLocal:'12',
      colorGlobal:'blue',
      fontSizeGlobal:'24'
    }
  }
}
</script>








globalDirective.vue

<template>
  <div class="hello">
    <h1>全局自定义指令demo</h1>
    <p v-my-global="{color:colorGlobal,fontSize:fontSizeGlobal}">我是内部组件使用了全局指令,任意地方都可以用到我哦~</p>
  </div>
</template>


<script>
//测试生命周期test
export default {
  name: 'globalDirective',
  props: {
    colorGlobal:{
      type:String,
      default:'blue'
    },
    fontSizeGlobal:{
      type:String,
      default:'24'


    }
  },
   data(){
    return{
      
    }
  }
}
</script>




自定义局部指令

(关键字为directives)

<template>
  <div class="hello">
    <h1>局部自定义指令demo</h1>
    <p v-my-local:argFoo.modifiersTest="{color:colorLocal,fontSize:fontSizeLocal}">我是局部指令</p>
  </div>
</template>


<script>
export default {
  name: 'localDirective',
  props: {
    colorLocal:{
      type:String,
    },
    fontSizeLocal:{
      type:String,
    }
  },
   data(){
    return{
      
    }
  },
  directives:{
    myLocal:{
      bind(el,binding,vnode) {
        //首次绑定dom,相当于第一次初始化
        console.log(el,binding,vnode)
        el.style.color=binding.value.color
        el.style.fontSize=binding.value.fontSize+'px'
      },
      update(el, binding, vnode) {
       //首次绑定dom,相当于第一次初始化
        console.log(el,binding,vnode)
        el.style.color=binding.value.color
        el.style.fontSize=binding.value.fontSize+'px'
      }
    }
  }
}
</script>




两个demo的最终效果展示图

完整项目地址

https://github.com/yzren/vue-directive

分享到此,希望对小伙伴有所帮助~

在看支持小布一下吧❤️

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值