【Vue.js】ミックスインの使い方と注意

## はじめに
仕事で使う事になったので1からVue.jsについて学んだ。ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

## ミックスインの使い方と注意
### ミックスインとは
[^オプション]: data(){}, filters(){}, など
Vue.jsのインスタンスのオプション[^オプション]を共通化させて再利用できるようにする仕組み。
以下の例では、`import { tokyoNumber } from "@/tokyoNumber";`としている部分でミックスイン`tokyoNumber`を読み込んでいる。

```vue:CountNumber.vue
<template>
  <div>
    <h2>{{ title | upperCase }}</h2>
    <h4>{{ subTitle | lowerCase }}</h4>
    <p>{{ number }}</p>
    <button type="button" class="btn btn-primary" @click="number++">+1</button>
  </div>
</template>

<script>
import { tokyoNumber } from "@/tokyoNumber";
export default {
  mixins: [tokyoNumber],
  /** ミックスインにより以下は宣言する必要がなくなる */
  //   data() {
  //     return {
  //       title: "Welcome to Tokyo",
  //       subTitle: "Tokyo is a great city",
  //       number: 0,
  //     };
  //   },
  //   filters: {
  //     upperCase(value) {
  //       return value.toUpperCase();
  //     },
  //     lowerCase(value) {
  //       return value.toLowerCase();
  //     },
  //   },
};
</script> 
```
```js:tokyoNumber.js
export const tokyoNumber = {
    data() {
        return {
            title: "Welcome to Tokyo",
            subTitle: "Tokyo is a great city",
            number: 0,
        };
    },
    filters: {
        upperCase(value) {
            return value.toUpperCase();
        },
        lowerCase(value) {
            return value.toLowerCase();
        },
    },
    created() {
        console.log('created in Mixin');
    },
}
```

ソースコード全体は以下。

https://github.com/yuta-katayama-23/intro-vuecli/commit/d513a105329f4a385b8130eae1992c507bc4d4b8

### ミックスインで定義しているオプションと同じオプションがコンポーネントにある場合、ミックスインとコンポーネントのオプションがマージされ、同じオプションについてはコンポーネント側が優先される

以下の例では、`data`の`title: "Welcome to Los",`がミックスインの`title: "Welcome to Tokyo",`と被っているが、この場合はコンポーネントの方のオプション（`title: "Welcome to Los",`）で上書きされるので画面は以下のようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/08b6bc6a-38c4-effa-fa16-ff090ff4bed9.png)
画像のソースコードは以下（tokyoNumber.jsは[上記](#ミックスインとは)と同じ。）

```vue:CountNumber.vue
<template>
  <div>
    <h2>{{ title | upperCase }}</h2>
    <h4>{{ subTitle | lowerCase }}</h4>
    <p>{{ number }}</p>
    <button type="button" class="btn btn-primary" @click="number++">+1</button>
  </div>
</template>

<script>
import { tokyoNumber } from "@/tokyoNumber";

export default {
  mixins: [tokyoNumber],
  data() {
    return {
      title: "Welcome to Los",
    };
  },
};
</script>
```
```vue.App.vue
<template>
  <div>
    <!-- 省略 -->
    <h2>{{ title | upperCase }}</h2>
    <h4>{{ subTitle | lowerCase }}</h4>
    <p>{{ number }}</p>
    <button type="button" class="btn btn-primary" @click="number++">+1</button>
    <hr />
    <CountNumber></CountNumber>
  </div>
</template>

<script>
import CountNumber from "./CountNumber.vue";
import { tokyoNumber } from "@/tokyoNumber";

export default {
  mixins: [tokyoNumber],
  components: {
    CountNumber,
  },
  // 省略
};
</script>
```
[^ライフサイクルフック関数]: https://qiita.com/yuta-katayama-23/items/578bb0cecf165fd850db#vue%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB
※ただし、ライフサイクルフック関数[^ライフサイクルフック関数]では、ミックスインのオプション・コンポーネントのオプションの両方が適用され、*ミックスインのオプション→コンポーネントのオプション*の順番で実行される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/cfa38e2c-f813-53f6-59ed-41d71a6bb2b6.png)

ソースコード全体は以下。

https://github.com/yuta-katayama-23/intro-vuecli/commit/0148cd364ed46dd21b7d4751a6e30630a2a36f6a

### グローバルミックスインとその注意点
#### グローバルミックスインとは
グローバルミックスインは、Single File Componentのグローバル登録・カスタムディレクティブのグローバル登録などと同じでグローバルにミックインを登録する事。
グローバルミックスインのオプション、ローカルミックスイン（コンポーネントの`mixins:`に宣言）のオプション、コンポーネントのオプションの3つのVueインスタンスのオプションが存在するが、それぞれ以下の順番で適用される。同じオプションがあればコンポーネントのそれで上書きされる。

1. グローバルミックスインのオプションに宣言された内容
1. ローカルミックスイン（コンポーネントの`mixins:`に宣言）のオプションに宣言された内容
1. コンポーネントのオプションに宣言された内容

#### 注意点
ただ、ミックスインのグローバル登録を行うと、自動的に全てコンポーネントに対してミックスインが登録される事になり、以下の画像で分かるように複雑になり分かりにくくなる。なので、基本は**グローバルミックスインは使わない。**
ライフサイクルフックの`created(){ console.log("global mixin"); }`オプションを持つグローバルミックスインを定義した時の、consoleの状態が以下の図。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/72800ed5-3efb-7f38-406f-31fc0a077ce4.png)

※グローバルミックスインを使う場面は、プラグインなどで全てのコンポーネントに適用させたい何かを定義した時などに限定するのが得策。

ソースコード全体は以下。

https://github.com/yuta-katayama-23/intro-vuecli/commit/0db1c316faa4a9a884951709a5d4cc714c0301a0

## Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

- https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4