Vue.jsのMixinsを利用することでコンポーネント内で定義されていないデータプロパティやメソッドをMixinsとしてコンポーネント外で定義し読み込むことでコンポーネント間で共有して利用することができます。例えば複数のコンポーネントで同じ処理内容のメソッドを記述している場合、同じコードを複数のコンポーネントに記述するのは冗長で非効率です。また同じ処理内容のメソッドに不具合があった場合にすべてのコンポーネントで修正しなければなりません。そのような場合にMixinsにコードを記述し共有化することで修正も一箇所で済み効率的にコードを管理することが可能となります。

Mixinsという名前からすると何か難しい機能なのではないかと思ってしまいそうですが動作確認を行えばすぐにどのようなものか理解できるので簡単なコードを使って説明を行っています。この文書を読めばMixinsが何か完全に理解することができます。

特にVue.jsの入門者の方であればあまり大きなアプリケーションを構築した経験がないので最初はMixinsのメリットが理解できないかもしれません。少し経験を積めばMixinsを使う場面に遭遇することもあるかと思いますのでこんな機能もあるのかと頭の片隅にMixinsという単語をとどめておいてください。

Mixinsからの機能追加

初期環境の設定

Mixinsを使ってデータプロパティを追加する前にindex.htmlファイルを作成し下記のコードを追加します。ここではvue.jsはcdnを利用して読み込んでいます。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Mixinsの理解</title>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<h1>{{ title }}</h1>
	</div>

	<script>
		const app = new Vue({
			el: '#app',
			data: {
				title : 'Hello Mixins',
			}
		})
	</script>
</body>
</html>

ブラウザにはHello Mixinsが表示されます。

初期画面
初期画面

データプロパティを追加する

Mixinsを使ってVueインスタンスの中で定義を行なっていないデータプロパティmessageをHTML内で使用します。

Mixinsを使ってデータプロパティを追加するためにはmyMixinオブジェクトをVueインスタンスとは別に作成します。ここではmyMixinという名前をつけていますが任意の名前をつけてください。

作成したmyMixinはmixinsプロパティでVueインスタンスに追加します。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Mixinsの理解</title>
	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
	<div id="app">
		<h1>{{ title }}</h1>
		<h2>{{ message }}</h2>
	</div>

	<script>
		const myMixin = {
			data(){
				return {
					message : 'hello from mixins',
				}
			},
		}

		const app = new Vue({
			el: '#app',
			mixins: [myMixin],
			data: {
				title : 'Hello Mixins',
			}
		})
	</script>
</body>
</html>

これだけの設定でmyMixinに設定したデータプロパティをVueインスタンスで利用することができます。

Vueインスタンス内で設定しているデータプロパティtitleと同様にMixinsを使って追加したmessageをブラウザ上に表示させることができます。このようにMixinを利用するとVue.jsのインスタンスとは別に定義したオブジェクトのデータプロパティを読み込んで使うことができます。

Mixinsを使って追加したmessageを表示
Mixinsを使って追加したmessageを表示
ここでは1つのファイルにVueインスタンスのコードとMixinsのコードを記述していますがVueプロジェクトからアプリケーションを構築している場合は別ファイルとしてMixinsを定義することになります。
fukidashi

追加したデータプロパティをcomputedプロパティで処理

Mixinsを通して追加したデータプロパティmessageをインスタンス内に定義したcomputedプロパティで操作できるのか確認してみます。

computedプロパティupperを追加して、toUpperCaseメソッドによりmessageをすべて大文字にします。


export const app = new Vue({
	el: '#app',
	mixins: [myMixin],
	data: {
		title : 'Hello Mixins',
	},
	computed:{
		upper(){
			return this.message.toUpperCase();
		},
	},
})

<div id="app">
	<h1>{{ title }}</h1>
	<h2>{{ upper }}</h2>
</div>

ブラウザで確認するとmessageが大文字になっていることが確認できます。このようにMixinsで追加したデータプロパティはVueインスタンスで設定しているデータプロパティと同じ操作ができることが確認できます。

messageを大文字に
messageを大文字に

メソッド、computedプロパティを追加する

メソッド、computedプロパティもデータプロパティと同様にMixinsで追加することができます。

myMixinオブジェクトの中でメソッドalert、computedプロパティupperを定義します。


const myMixin = {
	data(){
		return {
			message : 'hello from mixins',
		}
	},
	methods:{
		alert(){
			alert(this.message);
		},
	},
	computed:{
		upper(){
			return this.message.toUpperCase();
		},
	}
}

Mixinsを使って追加したメソッドalertとcomputedプロパティをhtml上に記述します。通常のVueインスタンスで定義したメソッドとcomputedプロパティと使用方法は同じです。


<div id="app">
	<h1>{{ title }}</h1>
	<h2>{{ upper }}</h2>
	<button @click="alert">Click Here</button>
</div>

ブラウザで確認してみましょう。新たにclickボタンが追加されていることが確認できます。

クリックボタン追加
クリックボタン追加

ボタンをクリックするとMixinsで追加しメソッドalertが実行され、アラート画面が表示されます。表示されている内容もMixinsで追加したmessageと同じ中身です。

Mixinsで追加したメソッドが実行
Mixinsで追加したメソッドが実行

インスタンスに同じメソッドが存在

Mixinsからメソッドを追加した際にVueインスタンスで定義したメソッド名と同じものが存在することが考えられます。

Mixinsで追加したメソッドとインスタンスに設定したメソッドがどちらが優先されるか確認しておきましょう。

VueインスタンスにもMixinsの中で定義した同じ名前のalertメソッドを追加しますが、表示させる内容はVueインスタンス内で定義したデータプロパティtitleです。


const app = new Vue({
	el: '#app',
	mixins: [myMixin],
	data: {
		title : 'Hello Mixins',
	},
	methods:{
		alert(){
			alert(this.title);
		},
	},
})

ブラウザで確認するとVueインスタンス内のデータプロパティtitleで定義したHello Mixinsが表示されるためVueインスタンスのメソッドがMixinsで追加したメソッドよりも優先的に実行されることがわかります。

同じ名前のメソッドalert実行
同じ名前のメソッドalert実行
データプロパティもcomputedプロパティもVueインスタンスの設定が優先されます。
fukidashi

ライフサイクルフックを追加する

Mixinsを使うとライフサイクルフックも追加することが可能です。ここではライフサイクルフックの一つであるcreatedを追加します。


const myMixin = {
	data(){
		return {
			message : 'hello from mixins',
		}
	},
	methods:{
		alert(){
			alert(this.message);
		},
	},
	computed:{
		upper(){
			return this.message.toUpperCase();
		},
	},
	created(){
		console.log('This is myMixin')
	}
}

ページを開くとブラウザのコンソール画面にThis is myMixinが表示されることが確認できます。ライフサイクルフックもMixinsで追加されることがわかります。

createdをVueインステンス側にも設定してどちらが先に実行されるのか確認しておきましょう。

実際にcreatedメソッドを両方(VueインスタンスとMixins)に追加し実行すると先にMixins側のcreatedが実行されその後にVueインスタンス側のcreatedが実行されることがわかります。

Mixinsファイルのimport

Mixinsを別ファイルで作成しimportを通して読み込むことで使用することができます。index.htmlファイルではimportは使用できないので、vueプロジェクトを利用している場合の読み込み手順の方法を記述しておきます。

src¥mixinsディレクトリを作成し、その中にmyMixin.jsファイルを作成し下記を記述します。


export const myMixin = {
	data(){
		return {
			message : 'hello from mixins',
		}
	},
	methods:{
		alert(){
			alert(this.message);
		},
	},
	computed:{
		upper(){
			return this.message.toUpperCase();
		},
	},
	created(){
		console.log('This is myMixin')
	}
}

コンポーネントであるvueファイルからパスを間違えないように以下のようにimportでmyMixinを読み込むとそのvueコンポーネントから追加したMixinsのデータプロパティ、メソッドなどを利用することが可能です。


import { myMixin } from '../mixins/myMixin.js'

export default {
  data(){
  	return {
  		title: 'Hello Mixins',
  	}
  },
  mixins : [myMixin],

}

mixinは1つだけではなくimportを使って複数のファイルから読み込むことで複数のmixinを設定することができます。その場合はmixinsプロパティの配列を[AMixin, BMixin, Cmixin]で記述することで実現できます。

グローバルMixinの設定

コンポーネント毎にMixinsを設定するのではなくグローバルにMixinを設定することができます。グローバルに設定するとすべてのコンポーネントで実行することができます。すべてのコンポーネントで実行できる反面、例えば複数のコンポーネントを利用している環境で以下のようなライフサイクルフックを設定した場合にコンソールタグには複数のメッセージが表示されます。複数のメッセージが表示されるのはすべてのコンポーネントでライフサイクルフックは実行されるためです。

グローバルMixinを利用する場合は注意が必要です。


Vue.mixin({
	created(){
		console.log('global mixin');
	}
});

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

ここまでの説明で基本的なMixinsの設定方法と動作確認を行いました。Mixinsってよく聞くけど何だろうと思っていた人も本文書を通して理解することができたのではないでしょうか。