1.Vue自定義指令
除了核心功能默認(rèn)內(nèi)置的指令 (
v-model和v-show等),Vue允許我們注冊(cè)自定義指令用于元素上。當(dāng)我們需要對(duì)普通 DOM 元素進(jìn)行底層操作時(shí),就可以用到用到自定義指令。
2. 鉤子函數(shù):
配置對(duì)象中包含一下幾個(gè)鉤子函數(shù)(均為可選值):
鉤子函數(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ā)生了改變,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見下)。
- componentUpdated: 指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用。
- unbind: 只調(diào)用一次,指令與元素解綁時(shí)調(diào)用。
3. 鉤子函數(shù)參數(shù):
指令鉤子函數(shù)會(huì)被傳入以下參數(shù):
el:指令所綁定的元素,可以用來直接操作 DOM。
-
binding:一個(gè)對(duì)象,包含以下 property:
name:指令名,不包括 v- 前綴。
value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值為 2。
oldValue:指令綁定的前一個(gè)值,僅在 update 和 componentUpdated 鉤子中可用。無論值是否改變都可用。
-
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)(這個(gè)參數(shù)本人沒有用過,有用過的大佬請(qǐng)指點(diǎn)一下)
oldVnode:上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和componentUpdated 鉤子中可用。
4.全局注冊(cè)
全局注冊(cè)自定義指令是將我們的自定義指令掛載到vue實(shí)例上的,在項(xiàng)目中都可以使用。
- 全局指令注冊(cè)方法為:Vue.directive(dName, options) 傳入兩個(gè)參數(shù)
- 分別是
指令名和配置對(duì)象 - 創(chuàng)建完之后,我們就可以使用 v-指令名 的方式加在元素上,以使自定義指令生效
4.1使 input 進(jìn)入獲取焦點(diǎn)
import Vue from 'vue'
// 注冊(cè)一個(gè)全局自定義指令 `v-focus`
Vue.directive('focus', {
// 當(dāng)被綁定的元素插入到 DOM 中時(shí)……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
- 使用
<input v-focus />
5.局部注冊(cè)
用法與 全局 注冊(cè)是一樣的, 只是寫法稍有不同
進(jìn)行局部注冊(cè)時(shí), 我們的組件中可以接收一個(gè)directives選項(xiàng),
其中,鍵為指令名 值為配置對(duì)象
- 注冊(cè)
export default{
data(){
return { ... }
},
directives:{
focus:{
inserted: function (el) {
//element-ui中 el-input外層是div, 里面包裹的才是input, 因此用在 el-input上的話,要讓el-input里的子元素聚焦
//增加判斷可以使我們的v-focus通用性更強(qiáng)
el.tagName == 'INPUT' ? el.focus() : el.children[0].focus
}
}
}
}
- 使用
<input v-focus></input>
6.項(xiàng)目用到的自定義指令
6.1 防抖函數(shù):
點(diǎn)擊按鈕過快可能多次請(qǐng)求接口,用自定義指令做全局的函數(shù)防抖
- 在main.js中 全局注冊(cè)一個(gè)自定義指令:
/**防抖函數(shù)
* @el :指令所綁定的元素,可以用來直接操作 DOM。
* @binding :綁定的事件或者值
*/
Vue.directive('debounce', {
inserted(el, binding) {
let timer = null
el.addEventListener('click', () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
binding.value();
timer = null;
}, 500)
})
}
})
- 使用
<button v-debounce="send">發(fā)送</button>
6.2節(jié)流函數(shù)
觸發(fā)高頻事件后,n秒內(nèi)函數(shù)函數(shù)只會(huì)執(zhí)行一次。
應(yīng)用場(chǎng)景: search搜索聯(lián)想,用戶在不斷輸入值時(shí)
- 在main.js中 全局注冊(cè)一個(gè)自定義指令
/**節(jié)流函數(shù)
* @el :指令所綁定的元素,可以用來直接操作 DOM。
* @binding :綁定的事件或者值
*/
Vue.directive('throttle', {
inserted(el, binding) {
let timer = null
el.addEventListener('change', () => {
if (!timer) {
timer = setTimeout(() => {
clearTimeout(timer)
binding.value();
timer = null;
}, 100)
}
})
}
})
- 使用
<input v-throttle="changeSearch" />