
vue自定義指令初探
一、什么是自定義指令
自定義指令是用來(lái)操作DOM的。盡管Vue推崇數(shù)據(jù)驅(qū)動(dòng)視圖的理念,但并非所有情況都適合數(shù)據(jù)驅(qū)動(dòng)。自定義指令就是一種有效的補(bǔ)充和擴(kuò)展,不僅可用于定義任何的DOM操作,并且是可復(fù)用的。
在vue中,除了核心功能默認(rèn)內(nèi)置的指令 (v-model 和 v-show),Vue 也允許注冊(cè)自定義指令。有的情況下,對(duì)普通 DOM 元素進(jìn)行底層操作,這時(shí)候就會(huì)用到自定義指令
二、自定義指令的核心知識(shí)
自定義指令分為鉤子函數(shù)和鉤子函數(shù)的參數(shù)
1、鉤子函數(shù)
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù) (均為可選):
bind:只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用。在這里可以進(jìn)行一次性的初始化設(shè)置。
inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在,但不一定已被插入文檔中)。
update:所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前。指令的值可能發(fā)生了改變,也可能沒(méi)有。但是你可以通過(guò)比較更新前后的值來(lái)忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見(jiàn)下)。
我們會(huì)在稍后討論渲染函數(shù)時(shí)介紹更多 VNodes 的細(xì)節(jié)。
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。
unbind:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
接下來(lái)我們來(lái)看一下鉤子函數(shù)的參數(shù) (即 el、binding、vnode 和 oldVnode)。
2、鉤子函數(shù)的參數(shù)
指令鉤子函數(shù)會(huì)被傳入以下參數(shù):
el:指令所綁定的元素,可以用來(lái)直接操作 DOM。 binding:一個(gè)對(duì)象,包含以下 property: name:指令名,不包括 v- 前綴。 value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2。 oldValue:指令綁定的前一個(gè)值,僅在 update 和 componentUpdated 鉤子中可用。無(wú)論值是否改變都可用。 expression:字符串形式的指令表達(dá)式。例如 v-my-directive="1 + 1" 中,表達(dá)式為 "1 + 1"。 arg:傳給指令的參數(shù),可選。例如 v-my-directive:foo 中,參數(shù)為 "foo"。 modifiers:一個(gè)包含修飾符的對(duì)象。例如:v-my-directive.foo.bar 中,修飾符對(duì)象為 { foo: true, bar: true }。 vnode:Vue 編譯生成的虛擬節(jié)點(diǎn)。移步 VNode API 來(lái)了解更多詳情。 oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和 componentUpdated 鉤子中可用。
三、動(dòng)態(tài)指令參數(shù)
指令的參數(shù)可以是動(dòng)態(tài)的。例如,在 v-mydirective:[argument]="value" 中,argument 參數(shù)可以根據(jù)組件實(shí)例數(shù)據(jù)進(jìn)行更新!這使得自定義指令可以在應(yīng)用中被靈活使用。
例如你想要?jiǎng)?chuàng)建一個(gè)自定義指令,用來(lái)通過(guò)固定布局將元素固定在頁(yè)面上。我們可以像這樣創(chuàng)建一個(gè)通過(guò)指令值來(lái)更新豎直位置像素值的自定義指令:
<div id="baseexample">
<p>Scroll down the page</p>
<p v-pin="200">Stick me 200px from the top of the page</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
el.style.top = binding.value + 'px'
}
})
new Vue({
el: '#baseexample'
})
// 這會(huì)把該元素固定在距離頁(yè)面頂部 200 像素的位置。但如果場(chǎng)景是我們需要把元素固定在左側(cè)而不是頂部又該怎么辦呢?這時(shí)使用動(dòng)態(tài)參數(shù)就可以非常方便地根據(jù)每個(gè)組件實(shí)例來(lái)進(jìn)行更新。
四 、vue bind和inserted的詳細(xì)區(qū)別
- 適用
需要對(duì)普通 DOM 元素進(jìn)行底層操作,這時(shí)候就會(huì)用到自定義指令
1.鉤子函數(shù)參數(shù)
除了 el 之外,其它參數(shù)都應(yīng)該是只讀的,切勿進(jìn)行修改
2.動(dòng)態(tài)指令參數(shù)
v-mydirective:[argument]=“value”
argument可以是動(dòng)態(tài)變化的,并且在鉤子里面實(shí)時(shí)更新的 4.鉤子區(qū)別
update 和 componentUpdated
共同點(diǎn):組件更新都會(huì)調(diào)用,update在componentUpdated之前
不同點(diǎn):
update 組件更新前的狀態(tài)
componentUpdated 組件更新后的狀態(tài)
場(chǎng)景:點(diǎn)擊事件,div的內(nèi)容追加 ??;
update(el, binding,vnode,oldVnode){
console.log(el.innerHTML); // <div>!</div>
}
componentUpdated(el, binding,vnode,oldVnode){
console.log(el.innerHTML); // //<div>?。?lt;/div>
}
// 注意: 區(qū)別是div里面的!數(shù)量
bind 和 inserted
共同點(diǎn): dom插入都會(huì)調(diào)用,bind在inserted之前
不同點(diǎn):
bind 時(shí)父節(jié)點(diǎn)為 null
inserted 時(shí)父節(jié)點(diǎn)存在。
bind是在dom樹(shù)繪制前調(diào)用,inserted在dom樹(shù)繪制后調(diào)用
bind: function (el) {
console.log(el.parentNode) // null
console.log('bind')
},
inserted: function (el) {
console.log(el.parentNode) // <div class="directive-box">...</div>
console.log('inserted')
}
五 、演示代碼
// 根據(jù)條見(jiàn)判斷 元素的顯示與隱藏
Vue.directive('changeColor', {
inserted:function(el, binding) {
el.style.color = 'red'
el.style.background = '#ccc'
// arg 獲取自定義指令的動(dòng)態(tài)參數(shù)
console.log("binding1",binding.arg)
if(binding.value < 3) {
el.style.display="none"
}else{
el.style.display="block"
}
},
update:function(el, binding,vnode,oldVnode){
console.log("vnode",vnode,oldVnode)
el.style.color = 'red'
el.style.background = '#ccc'
console.log("binding11",binding)
if(binding.value < 3) {
el.style.display="none"
}else{
el.style.display="block"
}
// 這個(gè)自定義指令會(huì)影響所有的使用數(shù)據(jù)
}
})
代碼僅供參考,代碼不全
// 在很多時(shí)候,你可能想在 bind 和 update 時(shí)觸發(fā)相同行為,而不關(guān)心其它的鉤子。比如這樣寫(xiě):
Vue.directive('changeColor',
function(el, binding) {
el.style.color = 'red'
el.style.background = '#ccc'
// arg 獲取自定義指令的動(dòng)態(tài)參數(shù)
console.log("binding1111111",binding.arg)
if(binding.value < 3) {
el.style.display="none"
}else{
el.style.display="block"
}
// 這個(gè)自定義指令會(huì)影響所有的使用數(shù)據(jù)
})
參考文章:https://blog.csdn.net/haduwi/article/details/104949560 vue bind和inserted的詳細(xì)區(qū)別
https://blog.csdn.net/qq_40299179/article/details/80086227
https://cn.vuejs.org/v2/guide/custom-directive.html
