6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue再利用と構成(Mixin)

Last updated at Posted at 2019-12-07

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()」はコンポーネント側が優先される

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名)、メソッド名から推測できるものにする
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?