Help us understand the problem. What is going on with this article?

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

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名)、メソッド名から推測できるものにする
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away