[Vue.js] mixin とコンポーネントのライフサイクルフックはどっちが先に実行されるかな
検証コードを書くまでもなく公式ガイドに答えが載っていました。ミックスインが先だそうです。
同じ名前のフック関数はそれら全てが呼び出されるよう配列にマージされます。ミックスインのフックはコンポーネント自身のフック前に呼ばれます。
同期的な処理ならこれで問題ないですが、ミックスインのフックで非同期処理を入れたところ、 await
の結果を待たずにコンポーネントの mounted()
が呼ばれました。
※下記サンプルは簡略化して別物になっていますが『ミックスインでページ内の全画像の読み込みを待ってからページコンポーネントで個別の処理を開始』ということをしたかった
サンプル
javascript
// ミックスイン
export default {
async mounted() {
console.log('mixin hook called')
await this.$_mounted_someMethod()
},
methods: {
// 5秒待ってから resolve() するだけの無意味なメソッド
$_mounted_someMethod() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('promise resolved')
resolve()
}, 5000)
})
}
}
}
javascript
// コンポーネント
import mounted from '@/mixins/mounted'
export default {
mixins: [mounted],
mounted() {
console.log('component hook called')
}
}
『ミックスインのフックが先に呼ばれる』となるとコンソールの表示は mixin hook called
→ 5秒後に promise resolved
→ component hook called
となりそうですが、実際には mixin hook called
→ component hook called
→ 5秒後に promise resolved
となります。
ミックスインの非同期処理を待ちたいときはどうすればいいか。
ソリューション
javascript
// ミックスイン
export default {
// mounted は削除してしまう
// async mounted() {
// console.log('mixin hook called')
// await this.$_mounted_someMethod()
// },
methods: {
// 5秒待ってから resolve() するだけの無意味なメソッド
$_mounted_someMethod() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('promise resolved')
resolve()
}, 5000)
})
}
}
}
javascript
// コンポーネント
import mounted from '@/mixins/mounted'
export default {
mixins: [mounted],
async mounted() { // async をつける
await this.$_mounted_someMethod() // コンポーネントの mounted() にてミックスインのメソッドを呼ぶ
console.log('component hook called')
}
}
ミックスインの mounted()
で呼んでいたメソッドをコンポーネント側で呼ぶように変更しただけです。
だいたいこんな感じでいいと思いますが、わざわざミックスインでやる必要がないですね。こんな使い方ならばプラグインとして共通化するほうがスマートだと思いました。