vue.js自定義指令詳解

寫在文本前:相信在作vue的項目,你確定接觸了指令,咱們經常使用vue內置的一些指令,好比v-model,v-text,v-if,v-show等等,可是這些內置指令不在本文的講解範疇,本文想說的是其自定義指令。思考一下,自定義指令咱們用在哪裏?是否是一會兒想不出來,感受作通常的項目不多用到指令呢,想不到指令用在哪!!由於咱們的確不多用,但不是說不會用。看官方api文檔裏有這麼一句話:普通 DOM 元素進行底層操做,這時候就會用到自定義指令。也就是說咱們在操做普通DOM的時候有可能會用到。在作項目的時候,咱們有不少種方法來替代自定義指令,因此讓咱們忽略了vue自定義指令的用處。下邊咱們一步步來了解vue自定義指令。javascript

舉幾個栗子

(一、輸入框焦點自動觸發。
(一、輸入框的電話號碼,郵箱,身份證號碼等的校驗。html

上面這幾個場合,咱們在作項目的時候徹底能夠用其餘方法代替,可是vue自定義指令能讓咱們作到一勞永逸,作到一處定義,全局調用。使其代碼簡潔高效,維護方便。接下來,咱們會一步步深刻vue自定義指令。vue

一、首先看下官方介紹,以下:

/*  自定義指 */
import Vue from 'vue'
/**
 * 模板
 * v-lang
 * 五個註冊指令的鉤子函數
 */
Vue.directive('mydirective', {
  /**
   * 1.被綁定
   * 作綁定的準備工做
   * 好比添加事件監聽器,或是其餘只須要執行一次的複雜操做
   */
  bind: function(el, binding, vnode) {
    console.log('1 - bind');
  },
  // 2.綁定到節點
  inserted: function(el, binding, vnode) {
    console.log('2 - inserted');
  },
  /**
   * 3.組件更新
   * 根據得到的新值執行對應的更新
   * 對於初始值也會調用一次
   */
  update: function(el, binding, vnode, oldVnode) {
    console.log('3 - update');
  },
  // 4.組件更新完成
  componentUpdated: function(el, binding, vnode, oldVnode) {
    console.log('4 - componentUpdated');
  },
  /**
   * 5.解綁
   * 作清理操做
   * 好比移除bind時綁定的事件監聽器
   */
  unbind: function(el, binding, vnode) {
    console.log('5 - bind');
  }
})
/**
鉤子函數
一、bind:只調用一次,指令第一次綁定到元素時調用,用這個鉤子函數能夠定義一個綁定時執行一次的初始化動做。
二、inserted:被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於document中)。
三、update:被綁定於元素所在的模板更新時調用,而不管綁定值是否變化。經過比較更新先後的綁定值,能夠忽略沒必要要的模板更新。
四、componentUpdated:被綁定元素所在模板完成一次更新週期時調用。
五、unbind:只調用一次,指令與元素解綁時調用。
*/

 

執行順序:
頁面加載時java

bind
inserted

 

組件更新時node

update
componentUpdated

 

卸載組件時express

unbind

 

官方地址請移步至,directive,上面只是作了個簡單的說明,接下來咱們詳細的介紹vue自定義指令的各個鉤子函數到底如何觸發。api

二、鉤子函數簡單講解

就我的而言, bind和update也許是這五個裏面最有用的兩個鉤子了.這個也是咱們下邊主要要說的2個鉤子函數。其它函數不經常使用,我也沒搞明白。ide

(1)鉤子函數 bind

bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。函數

<input id="input1" v-mydirective> // html元素

Vue.directive('mydirective', {
  bind: function(el, binding, vnode) {
   el.style.border = "1px solid red"
  }
}

 

上面代碼的效果就是輸入框的邊框變成了1像素的紅色。固然你也能夠設置其它試試。測試

<input id="input1" v-mydirective> // html元素

Vue.directive('mydirective', {
  bind: function(el, binding, vnode) {
    el.addEventListener('click', function (event) {
        alert('hellow world')
    })
  }
}

 

在bind鉤子函數裏,咱們能夠添加一些事件,在其某種條件下觸發(好比點擊事件,鍵盤事件),如上代碼,點擊input輸入框就會彈出 「hellow world」。至於bind裏面的參數的含義,建議本身動手輸入出來看看。很簡單是吧,下邊咱們來些稍微複雜一點的。看以下代碼:

指令鉤子函數會被傳入如下參數:

/**
鉤子函數的參數:(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鉤子函數中可用。
*/

 

這裏咱們着重注意一下,binding對象下的value,oldValue,arg,expression,modifiers這幾個屬性,根據這幾個屬性,咱們能夠作到更強大的自定義指令,下邊咱們參考案例來講:

<div v-mydirective:left="100" id=」box"></div> // html元素

Vue.directive('mydirective', {
  bind: function(el, binding, vnode) {
       el.style.position = 'fixed';
       const s = (binding.arg === 'left' ? 'left' : 'top');
       el.style[s] = binding.value + 'px';
  }
}

 

上面的代碼是使id=」box「的這個div元素絕對定位了,並且設置了left的值爲100px;

(2)鉤子函數 update

update:每當元素自己更新(可是子元素還未更新)時觸發。這句話怎麼理解呢?咱們用案例來講明,以下:

<template>
  <div id="box">
       <input v-model="myname" v-mydirective/>
  </div>
<template>
export default {
  data(){
    return{
      myname:"zhangshan"
    }
  },
  directives:{
    'mydirective':{
         update: function(el, binding, vnode, oldVnode) {
              console.log('update更新了');
         }
    }
  }
}

 

上邊代碼,輸入框默認值是"zhangshan",若是咱們修改了myname值,那麼就會觸發update函數的執行,輸出「update更新了」

再來個複雜一點的案例以下:

<template>
  <div id="box">
       <input type="text" v-model="myname"  v-mydirective="{type:'name',val:myname}"/>
       <input type="text" v-model="myemail"  v-mydirective="{type:'email',val:myemail}"/>
  </div>
<template>
export default {
  data(){
    return{
      myname:"zhangshan",
      myemail:'***@163.com'
    }
  },
  directives:{
    'mydirective':{
         update: function(el, binding, vnode, oldVnode) {
           //update:指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 
           if(binding.oldValue.val != binding.value.val){// 進行判斷,避免同時觸發多個判斷
             let checkStatus = true;// 定義驗證狀態 局部變量
             if(binding.value.type == 'name'){
                   if(binding.value.val.length>5){
                        checkStatus = false;
                        console.log("輸入的姓名長度大於5了")
                   }
             }
             if(binding.value.type == 'email'){// 驗證郵箱
               if(!/^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-   z0-9]+$/g.test(binding.value.val)){
                  checkStatus = false;
               }
             }
             if(checkStatus){
                el.style.border = "1px solid #333";//驗證經過input邊框顏色就變成#333
             }else{
                el.style.border = "1px solid red";//驗證不經過input邊框顏色就變成紅色
             }
         }
       }
    }
  }
}

 

上邊的案例,咱們經過bind下的modifiers屬性實現。modifiers:一個包含修飾符的對象;例如:v-my-directive.a.b,modifiers的值爲{'a':true,'b':true}。這樣咱們在update鉤子函數里根據所傳入的type類型作判斷來執行哪一個驗證方法。

(3)鉤子函數 inserted

inserted:被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於document中)。

<input id="input1" v-mydirective> // html元素

Vue.directive('mydirective', {
  inserted: function(el, binding, vnode) {
    el.focus()//輸入框自動獲取焦點
  }
}

 

對於鉤子函數 inserted,我也是隻知其一;不知其二,所用的很少,可是有個經常使用的方法是寫在這裏面的,就是輸入框自動獲取焦點,也就是上面的代碼。

(4)鉤子函數 bind和鉤子函數 inserted的區別。
據文檔所說,插入父節點時調用 inserted,來個測試。
bind: function (el) {
 console.log(el.parentNode) // null
 console.log('bind')
},
inserted: function (el) {
 console.log(el.parentNode) // <div id="login">...</div>這個元素是指令所在元素的父元素,具體根據本身的寫法不一樣
 console.log('inserted')
}

 

分別在兩個鉤子函數中輸出父節點:bind 時父節點爲 null,inserted 時父節點存在。

(5)鉤子函數 componentUpdated和鉤子函數 unbind
 // 4.組件更新完成
  componentUpdated: function(el, binding, vnode, oldVnode) {
        console.log('4 - componentUpdated')
  },
   /*** 5.解綁
     * 作清理操做
     * 好比移除bind時綁定的事件監聽器
   */
    unbind: function(el, binding, vnode) {
       console.log('5 - bind');
    }

 

對於這2個鉤子函數,沒有作太多的研究,unbind可能會用到,用於釋放實例資源佔用等操做。

關於vue.js指令大體也就說這麼多吧,若是錯誤,歡迎指正拍磚......

相關文章
相關標籤/搜索