在vue中除了官方提供的指令还允许自定义指令。

Vue2

语法
  • 全局注册指令
    Vue.directive(指令名,{
      bind:function(el,blinding, vNode){
        // 指令第一次绑定到元素时调用
        - el: 被绑定元素
        - blinding: 指令相关信息
        - vNode.context: 当前实例化对象
      }
      inserted:function(el,blinding, vNode){
        // 被绑定元素插入父节点时调用
      }
      update:function(el,blinding, vNode, oldVnode){
       // 所在组件的VNode更新时调用
      }
      componentUpdated:function(el,blinding, vNode, oldVnode){
      // 所在组件的VNode及其子VNode全部更新后调用
      }
      unbind:function(el,blinding, vNode){
       // 指令与元素解绑时调用
      }
    })
    
  • 局部注册-通过directives配置项注册
    directives:{
      指令名:{
        // 配置项与全局相同
      }
    } 
    
  • 注意点:
    [1] 指令名不带v-,vue创建指令时会自动加v- ,比如创建的指令为focus在trmplate中使用时使用v-focus
举例说明-input标签聚焦
<template>
  <div>
    <input v-focus>
  </div>
</template>
<script>
export default {
  directives:{
    'focus':{
      inserted: function(el){
        el.focus()
      }
    }
  }
}
</script>

input标签在页面打开时会自动聚焦

举例说明- 高亮设置

默认显示黄色背景高亮也可以通过选择更改高亮颜色

<template>
  <div>
    <div>
      <select name="" id="" v-model="color">
        <option :value="1">黄色</option>
        <option :value="2">红色</option>
      </select>
      <span v-highlight>111111111</span>
    </div>
  </div>
</template>
<script>
export default {
  data:function(){
    return{
      color: 1
    }
  },
  directives:{
    highlight:{
      bind: function(el){
        el.style.backgroundColor = 'yellow'
      },
      update: function(el, blinding, vnode){
        console.log(vnode.context)
        el.style.backgroundColor = vnode.context.color == 1 ? 'yellow' : 'red'
      }
    }
  }
}
</script>

Vue3

语法
  • 全局注册
    app = Vue.createApp({})
    app.directive(指令名,{
      created: function(){
       // 在绑定元素的属性或事件监听器被应用之前调用
      },
      beforeMount: function(el, binding, vnode, prevVnode){
        // beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用
      },
      mounted: function(el, binding, vnode, prevVnode){
        // mounted:在绑定元素的父组件被挂载后调用(相当于Vue2的inserted)
      },
      beforeUpdate: function(){
         // beforeUpdate:在更新包含组件的VNode之前调用
      },
      updated: function(el, binding, vnode, prevVnode){
        // updated:在包含组件的VNode及其子组件的VNode更新后调用
      },
       beforeUnmount: function(){
         // beforeUnmount:在卸载绑定元素的父组件之前调用
       },
        unmounted: function(){
          // unmounted:当指令与元素解除绑定且父组件已卸载时调用
        },
    })
    
举例说明-input聚焦
<template>
 <input type="text" v-focus>
</template>

<script>
export default {
 directives: {
   focus: {
     mounted(el) {
       el.focus();
     }
   }
 }
}
</script>
示例-防抖指令

防抖

app.directive('debounce',{
  mounted(el,blinding){
    // v-debounce:small='500' value==500 arg=='small'
    // v-debounce:500='goHome' value==goHome方法 arg==500
    const { value, arg } = blinding

    // 定义防抖的时间
    let delay = 500
    if(typeof value === 'number'){
      delay = value
    }else if(arg){
      delay = parseInt(arg)
    }
    // 定时器id
    let timer = null

    // 监听元素的点击事件
    el.addEventListener('click', function(){
      // 每次点击重新计时
      if(timer) clearTimeout(timer)
      timer = setTimeout(function(){
        // 到时间执行点击事件
        if (typeof value == 'function') value()
      }, delay)
    }, false)
  },
  beforeUnmount(el) {
    clearTimeout(el._debounceTimer)
  }
})
示例-节流指令
app.directive('debounce',{
  mounted(el,blinding){
   
    const { value, arg } = blinding

    // 定义节流的时间
    let delay = 500
    if(typeof value === 'number'){
      delay = value
    }else if(arg){
      delay = parseInt(arg)
    }
    
    let isLoading
    el.addEventListener('click', function(){
      // 每次之后轮次开始isLoading = true
      if ( isLoading ) return
      isLoading = true
      if (typeof value == 'function') value()
      setTimeout(function(){
        isLoading = false
      }, delay)
    }, false)
  },
  beforeUnmount(el) {
    clearTimeout(el._debounceTimer)
  }
})

更多推荐