寫在文本前:相信在作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
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;
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類型作判斷來執行哪一個驗證方法。
inserted:被綁定元素插入父節點時調用(父節點存在便可調用,沒必要存在於document中)。
<input id="input1" v-mydirective> // html元素 Vue.directive('mydirective', { inserted: function(el, binding, vnode) { el.focus()//輸入框自動獲取焦點 } }
對於鉤子函數 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 時父節點存在。
// 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指令大體也就說這麼多吧,若是錯誤,歡迎指正拍磚......