0%

Alex宅幹嘛_ReVue_Day14筆記_Directive

Custom Directives

這個部分要講自製 directive 的內容。
在自製 directive有以下幾個 hook 可以使用,分別為 bind, inserted, update, componentUpdated, unbind

以上這個範例可以看到我們自製了一個 directive 叫做 focus,然後,會在目標元素被掛到 DOM 上的時候,加入這個自製 directive 的效果。
另外,要特別注意的是自製 directive 要加在我們自製元件的 template 中喔,不要加到 HTML 文本裡面,會沒有效果。
那加入的內容有前綴詞是 v- ,它的後面就是加上我們自訂義的 directive 名稱,所以這邊的自製 directive 會是 v-directive。

全局註冊 v.s 局部註冊

全局註冊的方式,就是直接呼叫 Vue.directive 在物件外層註冊。
ex:

1
2
3
4
5
6
7
8
9
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})

new Vue({
el: '#app'
})

局部註冊:在元件內部註冊自訂義的 directive 的話,可以將其定義內容加到指定元件的 directives 屬性中。
ex:

1
2
3
4
5
6
7
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
}

Hook Function

這邊稍微介紹一下,自訂的 directive 所擁有的 hook 有哪些

  1. bind: 只會被呼叫一次。它的被呼叫時機為,當自製的 directive 被綁定到指定元件上時,會被呼叫。這個 hook 可以用來初始化一個被綁定元件。
  2. inserted: 當被綁定元件插入父元件中時,此 hook 會被呼叫。
  3. update: 所在元件更新時會發動,有可能比其所在元件所擁有的子元件更新前發動。
  4. componentUpdated: 所在元件更新,且該元件所擁有的全部子元件也更新後發動。
  5. unbind: 當此 directive 解綁時會發動。

以上這個範例,我們可以看到當元件被插入 DOM 時,會觸發 bind 和 inserted 這兩個 Hook,當更改 input 中的內容時,會更新所在元件的 message 資料,此時,會觸發 update 和 componentUpdated 這兩個 hook。

function shorhand

在上面的範例,可以看到我們的 directive 再創的時候,是用物件形式寫法來做定義的內容。
而官方文件也有提供一個 function 的寫法,若用 function 的寫法來定義的話,該 directive 會預設含有 bind 和 update 這兩個 hook。
ex:

1
2
3
Vue.directive('focus', function () {
// 定義內容
})

Directive Hook Arguments

在我們自訂義的 directive 所擁有的 hook 會帶入以下的參數

參數 內容 功能
el 可以取得 directive 所在的元件,可用來操縱所在元件的 DOM
binding 它是一個物件,它包含了以下的屬性
name 可以取得此沒有加上 v- 這個前綴詞的 directive 名稱
value 傳給 directive 的值,可以被這個屬性取得
oldValue 可以取得 value 的上一個舊值,只能在 update 和 componentUpdated 這兩個 hook 被取得。不管 value 有沒有被更改內容,此屬性的值都能被取得
expression 取得傳給 directive 的字串,注意是字串型別喔!!
arg 取得傳給 directive 的參數
modifiers 是一個具有修飾符的物件
vnode 由 Vue 編譯器所創出來的虛擬節點
oldVnode 前一個虛擬節點,只能在 update 和 componentUpdated 這兩個 hook 被取得

modifier feature

其中,modifiers 的引用方式比較特別一點,所以,在這邊紀錄一下

1
2
3
4
5
6
7
Vue.directive('focus', function(el, binding) {
console.log(binding)
})

const myComponent = {
template: `<p><input type="text" v-focus:landy.test1.test2 /></p>`
}

上面這個內容你可以看到我們在定義 myComponent 元件的 template 部分綁上自訂義的 v-focus,然後,後面接著 landy.test1.test2,那我們可以在
它的 console 中的 binding 屬性中的 arg 屬性看到其內容為 landy ,而 modifiers 屬性裡面會是一個物件,裡面包裹著兩個屬性分別為 test1 和 test2,然後,它們的值皆為 true。
可以看出來,先用冒號指定 arg 的對象,接著,才在這個 arg 後面使用 modifiers。

Dynamic Directive Arguments

在官方文件有講到,我們可以動態的變換傳入 directive 的 arg。

1
2
3
4
5
6
7
8
9
10
---HTML===
<p><input type="text" v-demo:[direction]="200" /></p>


---JavaScript---
new Vue({
data: {
direction: 'left'
}
})

可以看到我們用中括號把要傳入的 arg 內容包起來,那其 arg 的內容,可以由外部動態的更動,而 directive 可以利用 binding 的 arg 屬性來調用到這個傳入的 arg 內容。

Object Literals

direction 也可以接由外部傳進來的物件,接近來之後,我們再透過 direction 的 binding 的 value 內容來調用傳入的物件內容。

Alex 宅幹嘛 - 眉眉角角

Alex 提供的directive 範例

Alex 在課堂上提到一個它利用 directive 的功能來做的一個有關 grid system 展示的範例,因為,這個範例我蠻喜歡的,所以,紀錄一下

以上這個範例,我們先去偵聽 Vue 物件的 resize 事件,接著,在每一次觸發 resize 事件的時候,都會去更動到 Vue 物件中的 width 屬性值。
此時,我們利用我們自訂義的 v-width 這個 directive 來將 Vue 物件的 width 屬性值接進來,每當觸發 resize 就會去更動 v-width 所在元件的 directive 的 value 和 oldValue 值,
這個時候就會連帶的跑到 v-width 的 directive 定義的 function 裡面,去即時取得當下元件的寬度,顯示到畫面上,代表現在的格線區塊的寬度為多少,可以很好的展示給客戶看。

Directive 心法

注意~~~~~~~~~~~
以上這個範例, Alex 大大有傳遞一個觀念,我們可以偵聽較少元件的事件,並搭配 directive 的功用當其 binding 的數值因為偵聽事件觸發而變動,連帶的就會去觸發各 directive 所在的元件的 directive 定義的內容,以此機制去更動所在元件的內容。
用上面這種手法,我們就不需要每一個元件都要綁定屬於它自己的偵聽事件,當觸發多個偵聽事件時,可能因為多線程的緣故,而造成瀏覽器不可預知的錯誤,所以,可以想一下要怎麼利用 directive 這個工具喔~~