Vue.jsでアプリケーションを作る際、created
とmounted
をよく利用する。しかし、いざ他人に違いを説明するときに「なんかわかってるつもり」だったかもと思うことがあったので調べ直した。Vue2.xも3.xも、created
とmounted
についてはあまり変化はないように見える。 1
created
created
はコンポーネントのインスタンス生成後に呼び出されるdata
・computed
・watch
イベントなどの生成は完了している$el
(DOM要素のプロパティ)は未生成
mounted
$el
は生成済み$el
がマウント(=ブラウザにレンダリング)された直後に呼び出される
実際に動かしてみる
Vue3.xのプロジェクトで、ボタンを押すとDOM要素がカウントアップされるコンポーネントを作成した。検証方法はComplete Vue.js 3 (Inc. Composition API, Vue Router, Vuex)のLifecycle Hooks
の動画を参考にした。 2
created
とmounted
APIにconsole.info
を仕掛け、$el
を出力する。
// 抜粋 created() { console.info('created', this.$el, this.$data); }, mounted() { console.info('mounted', this.$el, this.$data); },
結果
created
では$el
は作成されていない。よってnull
が出力される。mounted
は$el
がマウントされた直後に呼び出されるため、$el
はnull
ではない。実際にレンダリングされているDOM要素が表示される。
その他
v-pre
APIを使うとbeforeMount
の前にDOM要素をレンダリングできる。Mustache記法({{}}
)そのものを表現したい場合などに利用する。
Vue2.x API — Vue.js
Vue3.x Built-in Directives | Vue.js
// scriptに追加 beforeMount() { console.info('beforeMount', this.$el, this.$data) },
<template> <div id="counter"> <p v-pre>{{v-pre nodes}} {{count}}</p> <p>Click Count {{count}}</p> </div> </template>
この<p>
タグ要素にv-pre
をつけるとMustache記法がそのままDOMに変換されていることがわかる。この段階では$el
はnullなのでイベントの検知はできない。
<template> <div id="counter"> <p v-pre>{{v-pre nodes}} {{count}}</p> <p>Click Count {{count}}</p> <div> <button v-pre @click="countUp">Click</button> ←ここは$elが生成されていないのでDOMExceptionになる <button class="reset-button" @click="resetCount">Reset</button> </div> </div> </template>
いつ使い分けるか?
画面表示前にAPIリクエストでパラメータをもらっておく…みたいな使い方が多いのかなと思う。
createdを使うとき
サーバーサイドレンダリング(SSR)はcreated
を使う。mounted
はSSRでは検知できないため。サーバーでレンダリングしたDOMを返して表示する仕組みと考えると、「それはそうかもな」と思った。また、レンダリング前に何か制御しておきたい場合もcreated
の段階で処理している。mounted
だと$el
生成後に発火するため、一瞬制御されない状態になってしまう。APIレスポンスパラメータに応じてルーティング先の制御をするときに使っているが、Vue RouterのbeforeEnter()
でやった方がいいかもしれない。
mountedを使うとき
基本はこっちを使っている。とにかく初期描画を早くしたいので、画面をレンダリング → レスポンスパラメータが取得できるまでは代わりの何かを用意、というふうに工夫しているため。data
の初期値をnull (undefined)
にしておき、「値がないときはスピナーを回す」というようにしておくとmounted
でAPIリクエストをしても問題なく画面描画できる。APIレスポンスが速ければcreated
でもいいかもしれない。ただ、とにかく初期描画を早くしたい!という要件であればこのようにするのが良いかなあと思っている。
所感など
Vue3.xだとOptions APIとComposition APIがあり、Composition APIはAPI名が異なるので注意が必要。調べたところcreated
はなくsetup()
になっていた。
図を見てわかったつもりになっていたが、実際に動かしてみた方が理解しやすいと改めて思った。