上一個篇章提到了基本的元件使用,雖然說是比較基礎的部分,但前前後後也寫了超過四千字的廢話。對於 Vue 比較熟悉的人來說,應該不會有什麼障礙才對。我們今天將會繼續提及,關於元件使用上的一些進階應用,也會接續上一篇比較沒有著墨的部分。
關於混合 Mixins
上一篇有約略提到 Mixins 的個特性,有曾經寫過 SCSS/SASS 的人應該對於這個東西不陌生。是的,他有點類似,也是將一些共用的函數提出去的一種作法。
實際上,Mixins 很類似一個元件的結構,只是他是被封裝成一個物件( Object ),然後透過元件的 mixins
屬性來導入。而 Mixins 本身有兩種作法,一種是寫給元件用,一種是可以註冊到 Vue 根元件上,也就是所謂的 全域 的概念。
// 這樣會定義一個全域的混合物件,大家都會套用。
Vue.mixin({
created: function () {
this.hello = 'world'
}
})
// 這樣只單純宣告一個混合物件,誰要用誰就將他引入。
let myMixin = {
created: function () {
this.hello = 'world'
}
}
然而,在 Vue 所提供的 Mixins 中,如果是數值的部分,會幫你把他合併,換句話說,如果你有一個 data ()
,然後你所使用的 Mixins 當中也有一個 data ()
,那麼,兩者所回傳的物件會被合併,當然,你必須要留意覆蓋問題。
<script>
let myMixin = {
data: function () {
return {
foo: 'bar'
}
}
}
export default {
name: 'MyComponent',
mixins: [myMixin],
data () {
return {
boo: 'bar'
}
}
}
</script>
上述的狀況,你的 data ()
就會自動合併,
倘若你的元件中,有使用到跟 Mixins 一樣的數值,那麼你元件的優先權是 永遠大於 Mixins 裡面的設定的,換句話說,Mixins 裡面相同的設定會被 覆蓋掉 。是的,即便是 computed
或是 methods
的設定,全部都會被元件本身 同名 的設定覆蓋掉,這一點在使用上需要留意。
另外,如果是與生命週期有關的函數,那麼 Mixins 的優先權則反過來,會 永遠大於 元件裡面生命週期函數。換句話說,你的函數執行,會優先執行 Mixins 的部分,接著再執行元件裡面的函數。
那麼,使用 Mixins 可以帶來什麼好處?
- D.R.Y.
- 增加元件可重用性。
- 可抽離核心程式碼與邏輯區塊。
壞處呢?
- 程式碼分離後不好維護。
- 程式碼分離後不好維護。
- 程式碼分離後不好維護。
對的,就是因為代碼分離,而且其實他沒有任何有效的機制可以管理。所以,這個部分僅能透過團隊自主規範,或是溝通協作的部分來維持。
Directive 指令
接著我們來談元件中自定義指令的部分。
我相信有寫過 Angular 的人對於 Directive 這件事情應該不陌生。是的,在 Vue 裡面,你在元件屬性上接上的諸如 v-bind
這一類的動作,就是內建的指令。然而這些指令,可以透過 Vue.directive()
或是元件內部的 directives
的方式來定義。兩者差異只是在一個是 全域 的,而一個只會作用在元件內部。
Vue.directive(
'focus',
{
inserted: function (el) {
el.focus()
}
}
)
/* OR */
export default {
name: 'MyComponent',
directives: {
focus: {
inserted (el) {
el.focus()
}
}
}
}
以照上述的例子,你在元件上面就會有一個叫做 v-focus
的指令可以使用。
指令本身有幾種勾子( Hook )可以使用:
bind
只會執行一次,在指令第一次被綁定到元件上時執行。inserted
當元件被加入父元件時執行,可保證父元件存在,但不保證元件已經進入父元件節點中。update
當元件更新時會呼叫此函數,但不能保證該元件其下的子元件都已更新。componentUpdated
當元件與其下的子元件都已更新完畢後,呼叫此函數。unbind
只會執行一次,在指令從元件被移除後執行。
而以上這幾種勾子,其所傳入的參數有:
el
當前元件的 DOM 節點。binding
返回一個物件對象,內容包含了:name
指令名稱,會去除掉v-
的前綴。value
指令綁定的回傳值。oldValue
上一次的回傳值,僅適用於update
與componentUpdated
。expression
指令綁定的回傳值,以字串形式回傳。arg
指令的後綴關鍵字,例如v-focus:boo
會回傳boo
。modifiers
指令的後綴修飾字,例如v-focus:boo.a
會回傳{ a: true }
vnode
Vue 所產生的虛擬節點。oldVnode
上一個虛擬節點,僅適用於update
與componentUpdated
。
另外,指令後面的關鍵字是可以動態分配的,例如:
<div v-show-ads:[scrollPosition]="200"></div>
這樣來說我們就可以定義哪一些 scrollPosition
等於 200 的時候,要做什麼事情,或是該下怎麼樣的設定爾等。
過濾器 Filters
最後我們來聊聊過濾器這個東西,當然不是什麼 BRITA 之類的東西。自定義的過濾器只能在在元件內部,或是全域,且是在宣告 Vue 應用程式之前就先做好,不然基本上過濾器是無效的。
Vue.filter(
'upperCase',
function (value) {
return value.toUpperCase()
}
)
/* OR */
export default {
name: 'MyComponent',
filters: {
upperCase (value) {
return value.toUpperCase()
}
}
}
過濾器本身的應用範圍有兩個,一個是 {{ }}
雙引號變數內,另外一個是可以在 v-bind
後面的變數值使用。
<template>
<section>
<h1>{{ hello | upperCase }}</h1>
<h2 v-bind:id="world | upperCase"></h2>
</section>
</template>
大概就是這樣,然後你可以串接一堆的過濾器來做事。
<template>
<section>
<h1>{{ hello | upperCase | lowerCase | upperCase }}</h1>
</section>
</template>
上面這個例子舉的比較不好。然後,由於過濾器本身就是 JavaScript 的函式,所以說,你也可以傳參數進去,
<template>
<section>
<h1>{{ hello | upperCase('arg1', arg2) }}</h1>
</section>
</template>
以上述的例子來說,你傳入給 upperCase ()
的參數就會有三個,
hello
這個變數是第一個。arg1
這會是第二個。arg2
這是第三個,依此類推。
小結
元件多數可以使用的部分,在這個章節已經交代的差不多了。比較進階的部分我們會在接下來的章節中陸續提到。當然也會給出相當的範例讓大家比較容易理解。
ITHome 鐵人賽同步刊登 Component 進階應用 Day 3