> ## Content Index
> Fetch the complete content index at: https://blog.hinablue.me/llms.txt
> Use this file to discover other available public pages before exploring further.

# [IT 鐵人賽] Component 進階應用 Day 3
- URL: https://blog.hinablue.me/2019-ithome-ironman-day-3/
- Published: 2019-09-04T01:46:00.000Z
- Updated: 2026-07-06T18:46:06.000Z
- Author: Hina Chen
- Tags: 2019, ITHome, Vue Component, VueJS, VueJS 2.0, JavaScript, 鐵人賽

上一個篇章提到了基本的元件使用，雖然說是比較基礎的部分，但前前後後也寫了超過四千字的廢話。對於 Vue 比較熟悉的人來說，應該不會有什麼障礙才對。我們今天將會繼續提及，關於元件使用上的一些進階應用，也會接續上一篇比較沒有著墨的部分。

---

## 關於混合 Mixins

上一篇有約略提到 Mixins 的個特性，有曾經寫過 SCSS/SASS 的人應該對於這個東西不陌生。是的，他有點類似，也是將一些共用的函數提出去的一種作法。

實際上，Mixins 很類似一個元件的結構，只是他是被封裝成一個物件（ *Object* ），然後透過元件的 `mixins` 屬性來導入。而 Mixins 本身有兩種作法，一種是寫給元件用，一種是可以註冊到 Vue 根元件上，也就是所謂的 **全域** 的概念。

```js
// 這樣會定義一個全域的混合物件，大家都會套用。
Vue.mixin({
 created: function () {
   this.hello = 'world'
 }
})

// 這樣只單純宣告一個混合物件，誰要用誰就將他引入。
let myMixin = {
  created: function () {
   this.hello = 'world'
  }
}

```

然而，在 Vue 所提供的 Mixins 中，如果是數值的部分，會幫你把他合併，換句話說，如果你有一個 `data ()`，然後你所使用的 Mixins 當中也有一個 `data ()`，那麼，兩者所回傳的物件會被合併，當然，你必須要留意覆蓋問題。

```html
<script>
let myMixin = {
  data: function () {
   return {
     foo: 'bar'
   }
  }
}

export default {
  name: 'MyComponent',
  mixins: [myMixin],
  data () {
    return {
      boo: 'bar'
    }
  }
}
</script>

```

上述的狀況，你的 `data ()` 就會自動合併，

![](https://blog.hinablue.me/content/images/2019/09/ithome_ironman_2019_day_3_1.png)

倘若你的元件中，有使用到跟 Mixins 一樣的數值，那麼你元件的優先權是 **永遠大於** Mixins 裡面的設定的，換句話說，Mixins 裡面相同的設定會被 *覆蓋掉* 。是的，即便是 `computed` 或是 `methods` 的設定，全部都會被元件本身 *同名* 的設定覆蓋掉，這一點在使用上需要留意。

另外，如果是與生命週期有關的函數，那麼 Mixins 的優先權則反過來，會 **永遠大於** 元件裡面生命週期函數。換句話說，你的函數執行，會優先執行 Mixins 的部分，接著再執行元件裡面的函數。

那麼，使用 Mixins 可以帶來什麼好處？

1. D.R.Y.
2. 增加元件可重用性。
3. 可抽離核心程式碼與邏輯區塊。

壞處呢？

1. 程式碼分離後不好維護。
2. 程式碼分離後不好維護。
3. 程式碼分離後不好維護。

對的，就是因為代碼分離，而且其實他沒有任何有效的機制可以管理。所以，這個部分僅能透過團隊自主規範，或是溝通協作的部分來維持。

---

## Directive 指令

接著我們來談元件中自定義指令的部分。

> [Custom Directive](https://vuejs.org/v2/guide/custom-directive.html?ref=blog.hinablue.me)

我相信有寫過 Angular 的人對於 Directive 這件事情應該不陌生。是的，在 Vue 裡面，你在元件屬性上接上的諸如 `v-bind` 這一類的動作，就是內建的指令。然而這些指令，可以透過 `Vue.directive()` 或是元件內部的 `directives` 的方式來定義。兩者差異只是在一個是 *全域* 的，而一個只會作用在元件內部。

```js
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 應用程式之前就先做好，不然基本上過濾器是無效的。

```js
Vue.filter(
  'upperCase',
  function (value) {
    return value.toUpperCase()
  }
)

/* OR */

export default {
  name: 'MyComponent',
  filters: {
    upperCase (value) {
      return value.toUpperCase()
    }
  }
}

```

過濾器本身的應用範圍有兩個，一個是 `{{ }}` 雙引號變數內，另外一個是可以在 `v-bind` 後面的變數值使用。

```html
<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 的函式，所以說，你也可以傳參數進去，

```html
<template>
  <section>
    <h1>{{ hello | upperCase('arg1', arg2) }}</h1>
  </section>
</template>

```

以上述的例子來說，你傳入給 `upperCase ()` 的參數就會有三個，

1. `hello` 這個變數是第一個。
2. `arg1` 這會是第二個。
3. `arg2` 這是第三個，依此類推。

---

## 小結

元件多數可以使用的部分，在這個章節已經交代的差不多了。比較進階的部分我們會在接下來的章節中陸續提到。當然也會給出相當的範例讓大家比較容易理解。

> ITHome 鐵人賽同步刊登 [Component 進階應用 Day 3](https://ithelp.ithome.com.tw/articles/10213770?ref=blog.hinablue.me)