こんにちは!
株式会社SCOUTER開発部フロントエンドエンジニアの佐藤(@r_sato1201)です
弊社ではフロントエンドのフレームワークにVue.jsやNuxt.jsを採用しています。 業務中で開発をしてる際に、Vueのライフサイクルフックについて理解が乏しいまま実装していることに気がついたので 今回はVueのライフサイクルフックについてまとめたいと思います。
ライフサイクルとは?
ライフサイクルフックについて話す前に、まずライフサイクルについて。 Vueに触れている方なら、上の図を一度は見たことがあると思います。 ライフサイクルとは、Vueインスタンスが生成されてから削除されるまでの流れのことで、上の図はその流れを表した図です。
Vueのライフサイクルは大きく分けて以下の5つに分けられます。
① Vueインスタンスの生成
② DOMへのマウント
③ 画面の更新、リアクティブデータの変更
④ Vueインスタンスの破棄
⑤ エラー時
それでは次に、上記の分類に沿ってライフサイクルフックを紹介したいと思います。
ライフサイクルフック
ライフサイクルフックとはVueのライフサイクルにおける一連の処理の中の各タイミングで実行する関数のことをいいます。 各フック内に記述することで、任意の処理を行うことができます。
先程記述したライフサイクルの5つの分類に沿ってライフサイクルフックを説明していきます。
① Vueインスタンスの生成
実行されるフック:beforeCreate
created
まずは Vueインスタンスが生成されます。この時点ではインスタンスがマウントされていないので、まだコンポーネントの内容は反映されていません。
Vueインスタンスが生成され、リアクティブデータが初期化される前にbeforeCreate
が呼ばれ、リアクティブデータが初期化された後にcreated
が呼ばれます。
② DOMへのマウント
実行されるフック:beforeMount
mounted
生成された Vueインスタンスは、次にDOMにマウントされます。
マウント前にbeforeMount
が呼ばれ、マウント後にmounted
が呼ばれます。
したがって、DOMにアクセス可能なのはmounted
以降になります。
③ 画面の更新、リアクティブデータの変更
実行されるフック:beforeUpdate
updated
Vueインスタンスのdata
が変更された場合や、props
で渡されているデータが親で変更された場合など、それらの値の変更のタイミングでDOMを自動的に更新し再描画します。その際に実行されるフックが上記2つです。
DOMが更新される前にbeforeUpdate
が、DOMが更新された後にupdated
が呼ばれます。
④ Vue インスタンスの破棄
実行されるフック:beforeDestroy
destroyed
v-ifなどの機能によりVueインスタンスが破棄された時、上記2つのフックが呼ばれます。
Vueインスタンスが破棄される直前にbeforeDestroy
が呼ばれ、Vueインスタンスが破棄された直後にdestroyed
が呼ばれます。
⑤ エラー時
実行されるフック:errorCaptured
任意の子孫コンポーネントからエラーをキャッチしたときに呼び出されます。
このフックは
・エラー
・エラーをトリガするVueインスタンス
・どこでエラーが捕捉されたかの文字列情報
これら3つの引数を受け取ります。
また、このフックではエラーが自分より上位に伝播するのを防ぐために、false を返すことができます。
表にしてまとめると以下のようになります。
ライフサイクルフックの一覧
フック名 | 説明 |
---|---|
beforeCreate | インスタンスが生成され、リアクティブデータが初期化される前 |
created | インスタンスが生成され、リアクティブデータが初期化された後 |
beforeMount | インスタンスがマウントされる前 |
mounted | インスタンスがマウントされた後 |
beforeUpdate | データが更新され、DOMに適用される前 |
updated | データが更新され、DOMに適用される前 |
beforeDestroy | インスタンスが破棄される直前 |
destroyed | インスタンスが破棄された直後 |
errorCaptured | 任意の子孫コンポーネントからエラーがキャプチャされたとき |
createdとmounted
ライフサイクルフックで使用頻度が高いのはcreated
とmounted
だと思います。
それぞれのユースケースをまとめてみました。
created
非同期通信を使ってデータを初期化するとき
よく使われるパターンとしてAPIなどを叩いて非同期通信で取得したデータをdata
に初期値として挿入する処理が挙げられると思います。
このケースでは初期化のタイミングで使うという面ではbeforeMount
やmounted
で 非同期通信を行ってもよいのですが、DOMのマウントが行われデータを画面に反映するまでの時間を少しでも減らすためにはcreated
を使う必要があります。また、beforeCreate
ではリアクティブデータが初期化されていないため、data
に挿入することができません。
mounted
DOMにアクセスする必要がある場合
DOM要素にアクセスする必要がある場合や、HTML要素の高さや幅を取得する場合の初期化処理はmounted
に記述するとよいでしょう。
ただし、mounted
は 全ての子コンポーネントがマウントされていることを保証しないことに注意してください。Vue全体がレンダリングされた後に処理を行いときは、vm.$nextTick
を使いましょう
mounted: function () { this.$nextTick(function () { // Vue全体がレンダリングされた後にのみ実行されるコード }) }
まとめ
Vueのライフサイクルについてまとめてみました。 今回触れなかったライフサイクルフックについても、分かりやすいユースケースなどあれば教えて頂けると幸いです!
さいごに
現在、株式会社SCOUTERでは、エンジニア、デザイナーの募集をしております。
興味のある方は、是非下記からご応募お願い致します!
参考資料
- 公式資料 (ライフサイクルダイアグラム)
https://jp.vuejs.org/v2/guide/instance.html#ライフサイクルダイアグラム