有的情況下徒恋,需要對普通 DOM 元素進行底層操作,這時候就會用到自定義指令欢伏。舉個聚焦輸入框的例子入挣,如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>el與data的兩種寫法</title>
<style></style>
</head>
<body>
<div id="app">
<h1>
當前的n值是:
<span v-text="n"></span>
</h1>
<h1>
當前的n值是:
<span v-big="n"></span>
</h1>
<button @click="n++">點我n+1</button>
<hr />
<input type="text" v-fbind:value="n" />
//通過element.innerText = binding.value * 10改變變n的綁定值,n可以是一個函數(shù)硝拧,默認參數(shù)為binding.value径筏,這樣就可以在該函數(shù)直接處理數(shù)據(jù)如下:divResize當成n
<div v-resize="divResize" class="header-wrapper"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
data: {
n: 1,
},
methods: {
divResize(data){
//data就是binding.value({height: style.height}) 的返回值
console.log("resizeData:",data)
},
}
//這種寫法寫起來簡單,但是不可以處理細節(jié)
directives: {
resize: {
// 綁定時調用
bind(el, binding){
let height = ""
function isResize(){
// 可根據(jù)需求障陶,調整內部代碼滋恬,利用binding.value返回即可
const style = document.defaultView.getComputedStyle(el)
if(height !== style.height){
// 此處關鍵代碼,通過此處代碼將數(shù)據(jù)進行返回,從而做到自適應
binding.value({height: style.height})
}
height = style.height
}
// 設置調用函數(shù)的延時,間隔過短會消耗過多資源
el.__vueSetInterval__ = setInterval(isResize, 100)
},
unbind(el){
clearInterval(el.__vueSetInterval__)
}
}
// big函數(shù)合適被調用 1杉辙、指令與元素成功綁定時(綁定時只是建立關系,頁面還沒出現(xiàn))會調用(一上來)勋拟,2、指令所在的模板被重新解析時
// 1妈候、函數(shù)寫法
big(element, binding) {
//第一個參數(shù)返回綁定指令的Dom元素敢靡,第二個參數(shù)為指令的對象
console.log(element)
console.log(binding)
element.innerText = binding.value * 10
console.log(element instanceof HTMLElement)
console.dir(element) //打印對象的詳細信息
},
//對象寫法,函數(shù)的寫法跟對象的寫法在于函數(shù)的寫法只執(zhí)行了bind苦银,update醋安,inserted是不執(zhí)行的
fbind: {
//指令與元素成功綁定時(綁定時只是建立關系,頁面還沒出現(xiàn))會調用(一上來)
bind(element, binding) {
console.log('bind')
element.value = binding.value
},
//指令所在元素被插入頁面時調用
inserted(element, binding) {
console.log('inserted')
element.focus()
},
//指令所在元素被重新解析頁面時調用
update(element, binding) {
console.log('updated')
element.value = binding.value
element.focus()
},
},
// bind update一般處理的邏輯都是一致的墓毒,函數(shù)的寫法跟對象的寫法在于函數(shù)的寫法只執(zhí)行了bind,update亲怠,inserted是不執(zhí)行的
/*注意點:
1所计、指令名的規(guī)范:<元素 v-big-num> 指令函數(shù)名需要加引號 'big-num'
*/
//下面寫法focus無效
// fbind(element, binding) {
// //第一個參數(shù)返回綁定指令的Dom元素,第二個參數(shù)為指令的對象
// element.value = binding.value
// element.focus();//Dom掛載到頁面才能調用团秽,這里的v-fbind只是指令與元素成功綁定時(綁定時只是建立關系主胧,頁面還沒出現(xiàn)),所以這里的focus無效
// },
// <button id="btn">點我創(chuàng)建一個input輸入框</button>
// var btn = document.getElementById("btn")
// btn.onclick = ()=>{
// const input = document.createdElement("input")
// input.focus()
// 需要等input出來才能focus习勤,因為是操作Dom了踪栋,DOM都還沒出來,添加樣式图毕,添加value等就不受影響
// 但是項像focus夷都,給input的父元素添加css,如 input.parentElement.style.bg = ""這些就需要放到appendChild后面
// console.log(input.parentElement)//null:還沒appendChild呢予颤,所以不知道input的父元素是誰囤官,
// document.body.appendChild("input")
// input.focus()
// }
},
})
// 全局指令的函數(shù)寫法
Vue.directives('big2', function (element, binding) {
console.log(element)
console.log(binding)
element.innerText = binding.value * 10
console.log(element instanceof HTMLElement)
console.dir(element) //打印對象的詳細信息
})
//全局指令的對象寫法
Vue.directives('fbind2', {
//指令與元素成功綁定時(綁定時只是建立關系冬阳,頁面還沒出現(xiàn))會調用(一上來)
bind(element, binding) {
console.log('bind')
element.value = binding.value
},
//指令所在元素被插入頁面時調用
inserted(element, binding) {
console.log('inserted')
element.focus()
},
//指令所在元素被重新解析頁面時調用
update(element, binding) {
console.log('updated')
element.value = binding.value
element.focus()
},
})
app.$mount('#app')
</script>
</body>
</html>
鉤子函數(shù)
指令定義函數(shù)提供了幾個鉤子函數(shù)(可選):
bind: 只調用一次,指令第一次綁定到元素時調用党饮,用這個鉤子函數(shù)可以定義一個在綁定時執(zhí)行一次的初始化動作肝陪。
inserted: 被綁定元素插入父節(jié)點時調用(父節(jié)點存在即可調用,不必存在于 document 中)刑顺。
update: 被綁定元素所在的模板更新時調用氯窍,而不論綁定值是否變化。通過比較更新前后的綁定值蹲堂,可以忽略不必要的模板更新(詳細的鉤子函數(shù)參數(shù)見下)狼讨。
componentUpdated: 被綁定元素所在模板完成一次更新周期時調用。
unbind: 只調用一次贯城, 指令與元素解綁時調用熊楼。
鉤子函數(shù)的參數(shù)有:
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: 傳給指令的參數(shù)学密。例如 v-my-directive:foo淘衙, arg 的值是 "foo"。
modifiers: 一個包含修飾符的對象腻暮。 例如: v-my-directive.foo.bar, 修飾符對象 modifiers 的值是 { foo: true, bar: true }彤守。
vnode: Vue 編譯生成的虛擬節(jié)點。
oldVnode: 上一個虛擬節(jié)點哭靖,僅在 update 和 componentUpdated 鉤子中可用具垫。
//九、vue-cli如何新增自定義指令试幽?
//1.創(chuàng)建局部指令
var app = new Vue({
el: '#app',
data: {
},
// 創(chuàng)建指令(可以多個)
directives: {
// 指令名稱
dir1: {
inserted(el) {
// 指令中第一個參數(shù)是當前使用指令的DOM
console.log(el);
console.log(arguments);
// 對DOM進行操作
el.style.width = '200px';
el.style.height = '200px';
el.style.background = '#000';
}
}
}
})
2.全局指令
Vue.directive('dir2', {
inserted(el) {
console.log(el);
}
})
3.指令的使用
<div id="app">
<div v-dir1></div>
<div v-dir2></div>
</div>