Vue再利用と構成(Mixin)

# Mixinとは
**公式から**
*ミックスイン (mixin) は、Vue コンポーネントに再利用可能で柔軟性のある機能を持たせるための方法です。ミックスインオブジェクトは任意のコンポーネントオプションを含むことができます。コンポーネントがミックスインを使用するとき、ミックスインの全てのオプションはコンポーネント自身のオプションに”混ぜられ”ます。*

*つまり、Mixinに書かれているものが読み込んだ先で利用できる(再利用できる)*

```mixins/mixin.js
export const myMixin = {
  created: function () {
    this.hello()
  },
  methods: {
    hello: function () {
      // eslint-disable-next-line no-console
      console.log('hello from mixin!')
    }
  }
}
```

**create時に「hello from mixin!」がconsoleに出力される**

```App.vue
<template>
  <div></div>
</template>

<script>
import { myMixin } from "./mixins/mixin";

export default {
  mixins: [myMixin]
};
</script>
```

## オプションのマージ

### データのマージ
```mixins/mixin.js
export const myMixin = {
  data: function () {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}
```

**dataがマージされ、「foo追加」「messageはgoodbyeで上書き」となる**

```App.vue
<template>
  <div></div>
</template>

<script>
import { myMixin } from "./mixins/mixin";

export default {
  mixins: [myMixin],
  data: function() {
    return {
      message: "goodbye",
      bar: "def"
    };
  },
  created: function() {
    // eslint-disable-next-line no-console
    console.log(this.$data);
    // => { message: "goodbye", foo: "abc", bar: "def" }
  }
};
</script>
```

### フック関数のマージ
```mixins/mixin.js
export const myMixin = {
  created: function () {
    // eslint-disable-next-line no-console
    console.log('mixin hook called')
  }
}
```

**mixin「created」⇒component「created」の順に実行される**

```App.vue
<template>
  <div></div>
</template>

<script>
import { myMixin } from "./mixins/mixin";

export default {
  mixins: [myMixin],
  created: function () {
    // eslint-disable-next-line no-console
    console.log('component hook called')
  }
};
</script>
// => "mixin hook called"
// => "component hook called"
```

### methodsのマージ
*オブジェクトの値を期待するオプションは、例えば、methods、components、そして directives らは同じオブジェクトにマージされます。コンポーネントオプションはこれらのオブジェクトでキーのコンフリクトがあるとき、優先されます:*

```mixins/mixin.js
export const myMixin = {
  methods: {
    foo: function () {
      // eslint-disable-next-line no-console
      console.log('foo')
    },
    conflicting: function () {
      // eslint-disable-next-line no-console
      console.log('from mixin')
    }
  }
}
```

```App.vue
<template>
  <div></div>
</template>

<script>
import { myMixin } from "./mixins/mixin";

export default {
  mixins: [myMixin],
  methods: {
    bar: function() {
      // eslint-disable-next-line no-console
      console.log("bar");
    },
    conflicting: function() {
      // eslint-disable-next-line no-console
      console.log("from self");
    }
  }
};
</script>
```
**methodsがマージされ、「conflicting()」はコンポーネント側が優先される**

```js
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
```


### MixinのMixin

```mixins/mixin.js
export const myMixin = {
  data: function () {
    return {
      foo: 'abc'
    }
  }
}
```
```mixins/mixin2.js
export const myMixin2 = {
  data: function () {
    return {
      bar: 'def'
    }
  }
}
```

```mixins/marge-mixin.js
import { myMixin } from "./mixin";
import { myMixin2 } from "./mixin2";

export const myMixinx = {
    mixins: [myMixin,myMixin2]
}
```

```App.vue
<template>
  <div></div>
</template>

<script>
import { myMixinx } from "./mixins/marge-mixin";

export default {
  mixins: [myMixinx],
  created: function() {
    // eslint-disable-next-line no-console
    console.log(this.$data);
    // => { foo: "abc", bar: "def" }
  }
};
</script>
```

# Mixinの利用方針

- グローバルは極力使わない
- 名前の競合は基本しない
- そのコンポーネントに極力必要な分だけimportする(コンポーネントで使用しないdataやmethodを減らす)
- コンポーネントのthisを参照するような密結合な設計はしない
- Mixinがコンポーネントからの暗黙的な利用にならないよう、ファイル名(import名)、メソッド名から推測できるものにする