一、自定義全局指令
開門見山 舉個栗子:
<label>
搜索
<input type="text" id="search">
</label>
此時 若要觸發這個輸入框的獲得焦點事件 在原生方法中是這樣的:
document.getElementById("search").focus();
而在Vue中 使用自定義指令來實現該效果
指令 就是形如v-model v-text之類的 只不過這些是Vue默認提供的
而自定義指令 就是自定義的(廢話
在Vue中 所有的指令使用的時候都以v-
開頭
自定義一個名爲v-focus的自定義指令:
加在標籤中
<label>
搜索
<input type="text" id="search" v-focus>
</label>
然後 用Vue.directive()來定義全局指令
語法:Vue.directive(指令名稱,對象)
第一個參數是指令的名稱 在定義的時候 指令前面無需加上v-的前綴 但在調用的時候必須加
第二個參數是個對象 該對象上面有一些指令相關的鉤子函數 這些函數可以在特定階段執行相關的操作
在每個鉤子函數中 第一個參數永遠是el 其表示被綁定了該指令的元素(element)【當然 參數名可隨意取】
它是原生的js的dom對象 因此可以在其上面盡情使用js方法
常用的鉤子函數有bind inserted和updated:
- bind是每當指令綁定到元素上時 會立即執行該bind函數
其只會執行一次 因爲一個指令只能綁定到一個元素上一次 - inserted是當元素插入到DOM中的時候會執行該inserted函數
其也只會執行一次 - updated是當DOM節點(VNode組件)更新的時候 會執行該upload函數
可能會觸發多次
Vue.directive("focus",{
// 鉤子函數
// 在bind剛綁定的時候 元素還並沒有被放到dom中去 因此此時調用focus()方法沒作用 不會生效 因爲一個元素只有在插入dom之後才能獲取焦點
bind:function(el)
{
// el.focus();
},
// 元素插入到DOM中的時候會執行該inserted函數
// 【只會執行一次】
inserted:function(el)
{
el.focus();
},
// 當DOM節點(VNode組件)更新的時候 會執行該upload函數
// 【可能會觸發多次】
updated:function(el)
{
}
})
除此之外 還有:
- componentUpdated:指令所在組件的DOM節點(VNode組件)及其子DOM節點(VNode組件)全部更新後調用
- unbind:指令與元素解綁時調用
只調用一次
如此 即可實現自定義指令了
當然 樣式和行爲還是有區別的:
何爲樣式?樣式就是比如設置顏色之類的
而行爲 就是比如focus()之類的js行爲
拿自定義字體顏色指令舉個栗子吧:
Vue.directive("color",{
bind:function(el)
{
el.style.color="aqua";
}
})
我們發現樣式是可以在bind裏設置的
那是因爲因爲只要樣式被解析了 那麼顯示在頁面上就會帶有顏色
樣式只要通過指令綁定給了元素 不管這個元素有沒有被插入到頁面中去 這個元素肯定會有了一個內聯樣式
在那之後 元素肯定會顯示到頁面中 在這個時候 瀏覽器的渲染引擎必然會解析樣式 然後應用給該元素
但 focus()之類的方法是一個行爲 行爲必須添加到DOM中才能獲得焦點 在bind的時候還只是在內存中 並沒有添加到DOM上
在內存中調用的行爲 然後再渲染到頁面上時 自然是無效的
而insert是到了頁面上之後才調用 因此行爲會有效
總而言之 和js行爲有關的操作最好在inserted裏執行 防止js行爲不生效
而 和樣式相關的操作 通常可以放在bind中執行
在自定義指令中拿到傳遞的值
在定義的時候 要加上引號 因爲傳遞的是一個字符串
若不加引號 則會識別爲是一個變量
<input type="text" id="search" v-color="'blue'">
首先 看一下鉤子函數共有哪些參數:
el
:指令所綁定的元素 可用來直接操作DOMbinding
:一個對象 包含以下屬性:
name:指令名(不包括v-前綴)
value:指令的綁定值
例:在v-my-directive=“1+1"中 綁定值是爲2 即:value是經過字符串解析後的結果
oldValue:指令綁定的前一個值
僅在update和componentUpdated鉤子中可用
無論值是否改變都可用
expression:字符串形式的指令表達式
例:在v-my-directive=“1+1"中 表達式爲"1+1” 即:expression是不經過字符串解析後的結果 原原本本的結果
arg:傳給指令的參數
例:在v-my-directive:foo中 參數爲"foo”
modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象爲 { foo: true, bar: true }vnode
:Vue 編譯生成的虛擬節點oldVnode
:上一個虛擬節點
僅在update和componentUpdated鉤子中可用
拿到傳遞的值
例:
// 自定義設置字體顏色指令
Vue.directive("color",{
bind:function(el,binding) // 此處的el和binding可任意命名
{
console.log(binding.value);
el.style.color=binding.value;
}
})
二、自定義私有指令
就像過濾器一樣 指令也是不但有共有的指令 也有私有的指令
自定義私有指令其實和自定義私有過濾器類似
都是在Vue實例中的屬性對象裏進行設置
<div id="app2">
<h3 v-fontWeight="1000">{{date | dateFormat}}</h3>
</div>
<script>
var vm2=new Vue({
el:'#app2',
data:{
date:new Date()
},
methods:{},
filters:{},
// 自定義私有指令
directives:{
"fontweight":{
bind:function(el,binding)
{
el.style.fontWeight=binding.value;
}
}
}
})
</script>
三、指令的簡寫
Vue的自定義指令還支持簡寫
如果只想在bind
和update
這兩個鉤子上進行重複的動作
且不關心其它的鉤子函數
那麼 可以直接在指令名後面跟上方法
例:
<div id="app2">
<h3 v-fontWeight="1000" v-fontsize="'50'">{{date | dateFormat}}</h3>
</div>
<script>
var vm2=new Vue({
el:'#app2',
data:{
date:new Date()
},
methods:{},
filters:{},
// 自定義私有指令
directives:{
// 字體粗細
"fontweight":{
bind:function(el,binding)
{
el.style.fontWeight=binding.value;
}
},
// 字體大小
"fontsize":function(el,binding) // 該function就相當於將裏面的代碼寫到【且只寫到】bind和update鉤子上去了
{
el.style.fontSize=parseInt(binding.value)+"px";
}
}
})
</script>