# ミックスイン

# 基本

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

例:

// ミックスインオブジェクトを定義
const myMixin = {
  created() {
    this.hello()
  },
  methods: {
    hello() {
      console.log('hello from mixin!')
    }
  }
}

// このミックスインを使用する app を定義
const app = Vue.createApp({
  mixins: [myMixin]
})

app.mount('#mixins-basic') // => "hello from mixin!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# オプションのマージ

ミックスインとコンポーネントそれ自身が重複したオプションを含むとき、それらは適切なストラテジを使用して"マージ"されます。

例えば、データオブジェクトは再帰的にマージされ、コンフリクトした場合にはコンポーネントのデータが優先されます。

const myMixin = {
  data() {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  data() {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created() {
    console.log(this.$data) // => { message: "goodbye", foo: "abc", bar: "def" }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

同じ名前のフック関数はそれら全てが呼び出されるよう配列にマージされます。ミックスインのフックはコンポーネント自身のフックに呼び出されます。

const myMixin = {
  created() {
    console.log('mixin hook called')
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  created() {
    console.log('component hook called')
  }
})

// => "mixin hook called"
// => "component hook called"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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

const myMixin = {
  methods: {
    foo() {
      console.log('foo')
    },
    conflicting() {
      console.log('from mixin')
    }
  }
}

const app = Vue.createApp({
  mixins: [myMixin],
  methods: {
    bar() {
      console.log('bar')
    },
    conflicting() {
      console.log('from self')
    }
  }
})

const vm = app.mount('#mixins-basic')

vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# グローバルミックスイン

Vue アプリケーションのためにグローバルにミックスインを適用することもできます:

const app = Vue.createApp({
  myOption: 'hello!'
})

// `myOption` カスタムオプションにハンドラを注入する
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

app.mount('#mixins-global') // => "hello!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用に注意してください!一度、グローバルにミックスインを適用すると、それはその後にアプリ内で作成される全ての Vue コンポーネントインスタンスに影響します。 (例えば、子コンポーネント):

const app = Vue.createApp({
  myOption: 'hello!'
})

// `myOption` カスタムオプションにハンドラを注入する
app.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

// myOption を子コンポーネントにも追加
app.component('test-component', {
  myOption: 'hello from component!'
})

app.mount('#mixins-global')

// => "hello!"
// => "hello from component!"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

ほとんどの場合、上記の例のようなカスタムオプションを処理するものだけに使用すべきです。重複適用を避けるために、それらを プラグイン として作成することも良い方法です。

# カスタムオプションのマージストラテジ

カスタムオプションがマージされるとき、それらは既存の値を上書きするデフォルトのストラテジを使用します。カスタムロジックを使用してカスタムオプションをマージしたい場合は、app.config.optionMergeStrategies をアタッチする必要があります。

const app = Vue.createApp({})

app.config.optionMergeStrategies.customOption = (toVal, fromVal) => {
  // マージされた値を返す
}
1
2
3
4
5

マージストラテジは、親・子インスタンスで定義されたオプションの値をそれぞれ 1 番目、2 番目の引数として受け取ります。ミックスインを使用するときに、これらのパラメータに何が入っているかを確認してみましょう:

const app = Vue.createApp({
  custom: 'hello!'
})

app.config.optionMergeStrategies.custom = (toVal, fromVal) => {
  console.log(fromVal, toVal)
  // => "goodbye!", undefined
  // => "hello", "goodbye!"
  return fromVal || toVal
}

app.mixin({
  custom: 'goodbye!',
  created() {
    console.log(this.$options.custom) // => "hello!"
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

上記の通り、コンソールには最初にミックスインから、次に app から出力された toValfromVal が表示されます。fromVal が存在する場合には常にそれが返されるため、最終的には this.$options.customhello! がセットされます。ストラテジを常に子インスタンスの値を返すように変更してみましょう:

const app = Vue.createApp({
  custom: 'hello!'
})

app.config.optionMergeStrategies.custom = (toVal, fromVal) => toVal || fromVal

app.mixin({
  custom: 'goodbye!',
  created() {
    console.log(this.$options.custom) // => "goodbye!"
  }
})
1
2
3
4
5
6
7
8
9
10
11
12

Vue 2 では、ミックスインはコンポーネントロジックの一部を再利用可能なチャンクに抽象化する主要なツールでした。ただし、いくつかの問題があります:

  • ミックスインはコンフリクトしやすい: それぞれの機能のプロパティが同じコンポーネントにマージされるため、プロパティ名のコンフリクト回避とデバッグのために、全ての他の機能について知っておく必要があります。

  • 再利用性は制限されている: ロジックを変更するためのパラメータをミックスインに渡せないことは、抽象化ロジックに関する柔軟性を低下させます。

これらの問題に対処するため、論理的な関心事によってコードを整理する新しい方法を追加しました: コンポジション API

Deployed on Netlify.
最終更新日: 9/24/2020, 11:34:42 PM