-
使用場(chǎng)景
除了核心功能默認(rèn)內(nèi)置的指令,Vue 也允許注冊(cè)自定義指令, 在你需要對(duì)普通 DOM 元素進(jìn)行底層操作的情況下,這時(shí)候就會(huì)用到自定義指令directive。
-
注冊(cè)方式以及用法
directive 分為全局注冊(cè)以及局部注冊(cè)兩種,注冊(cè)后在標(biāo)簽上使用 v- 注冊(cè)名 即可使用,在下例中,使用 v-name
// 全局注冊(cè)
Vue.directive('name',function(){
// do something
});
// 局部注冊(cè)
new Vue({
directives:{
name:{
// do something
}
}
});
-
鉤子函數(shù)
在注冊(cè)
directive時(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ā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來(lái)忽略不必要的模板更新 。 -
componentUpdated: 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。 -
unbind: 只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
-
我們?cè)阢^子函數(shù)中可以獲取到以下參數(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)oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在update和componentUpdated鉤子中可用
注意!除了
el之外,其它參數(shù)都應(yīng)該是只讀的,切勿進(jìn)行修改。如果需要在鉤子之間共享數(shù)據(jù),建議通過元素的dataset來(lái)進(jìn)行。
舉個(gè)例子,我們?cè)陧?xiàng)目中的按鈕需要通過權(quán)限來(lái)控制是否渲染,那么我們可以做一個(gè)權(quán)限指令來(lái)判斷是否渲染,
<template>
<div>
<button v-permission="['add_btn']">新增</button>
<button v-permission="['edit_btn']">編輯</button>
<button v-permission="['remove_btn']">刪除</button>
</div>
</template>
<script>
// 模擬從后端拿到權(quán)限數(shù)據(jù)為一個(gè)數(shù)組,里面有新增以及編輯兩個(gè)按鈕權(quán)限:
const data = [ 'add_btn', 'edit_btn' ]
export default {
name: '',
directives: {
// 定義一個(gè) permission 的指令
permission: {
// 在節(jié)點(diǎn)被插入父節(jié)點(diǎn)時(shí)調(diào)用
inserted (el, binding, vnode) {
const { value } = binding
const permissionRoles = value
const hasPermission = data.some(role => {
return permissionRoles.includes(role)
})
// 如果沒有權(quán)限,則移除按鈕節(jié)點(diǎn)
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
}
}
</script>
這樣,就完成了一個(gè)按鈕級(jí)別的權(quán)限管理, 自定義指令當(dāng)然還有更多的用處,比如按鈕的點(diǎn)擊波紋,按鈕點(diǎn)擊請(qǐng)求返回前的禁用,某節(jié)點(diǎn)加載時(shí)loading,如開頭所說(shuō)的,在你需要對(duì)普通 DOM 元素進(jìn)行底層操作的情況下,這時(shí)候就會(huì)用到自定義指令directive。