ryoのぼやき

技術についての学習内容のまとめです。

【Vue.js】Vueにおけるライフサイクルフックの使い分け

この記事の内容

Vue.jsには、createdmountedさらにはupdatedなど、
関数を定義できる場所が複数あり、
どこで何を書くべきなのかよく分からなくなりがちです。

これらはライフサイクルフックというもので
それぞれの使いどきは、
どんなタイミングで実行したいのかによって決まります。

そのため、これらを理解するには、
Vueインスタンスが生成されてから破棄されるまでの流れ、
つまり、(名前の通り)「ライフサイクル」を理解することが最初の一歩につながります。

そんなわけで、Vueインスタンスのライフサイクルについて調べてことを書きたいと思います

インスタンスの生成、初期化

まずは、new Vue()によって、Vueインスタンスが生成されます。
生成された後は、初期化処理を行います。
この初期化処理の過程で、「リアクティブデータの初期化」が行われます。
この初期化が行われると、
dataの更新が画面の表示と同期されるようになるわけです。

そして、この「リアクティブデータの初期化」の前後に行われるフックが
それぞれあります。

まず、初期化の前に行われるフックが、beforeCreateです。
この段階では、dataなどのデータが初期化されていないので、
読み込もうとしてもundefinedとなります。

そして、初期化の後に行われるフックが、createdです。
この段階には、リアクティブデータの初期化が住んでいるので、
dataを読み込むことができます。

<フックの使いどころ例>
beforeCreate
パッと使いどころが思い浮かばなかったのですが、 公式ドキュメントでは、循環参照をするコンポーネント群は
コンポーネント登録をする時に、無限ループに陥るので、
片方のコンポーネントがもう一方をコンポーネント
初期登録するまで待つような処理をする必要があり、
そのような処理をする際には、beforeCreateで行うようです。

created
ここでは、APIを呼んでサーバなどからの
データ取得処理を書くことが多いです。
他には、DOMへのマウントが完了して
画面が描画されるまでのローディングの表示処理も
ここで書いたりします。

マウント

このフェーズでは、コンポーネントがDOMにマウントされます。
つまり、VueインスタンスとDOMが紐付けされます。

具体的な流れとしては、
まず、Vueインスタンスelオプションが指定されているかが確認されます。
されている場合は、そのまま次のフェーズに移りますが、
このオプションが指定されていない場合は、mount関数が実行されたタイミングで、
次のフェーズに移ります。

その後はtemplateオプションを持っているかが確認されます。
持っている場合は、templateがrender関数にコンパイルされます。
持っていない場合は、elオプションで定義されたDOMをtemplateとして、
コンパイルします。

そして、ようやくマウントが行われます。
つまりインスタンスのelement(vm.$el)を作成し、elオプションに置換します。

ここで、このマウントの前に実行されるフックがbeforeMountです。
また、マウントの後に実行されるフックはmountedです。(これはよく使いますよね)

<フックの使いどころ例>
beforeMount
ここに関しても、実際の使用ケースは浮かばなかったのですが、
使いどころとしては、Vueのelementに置き換わる前のelement要素に
アクセスする処理はここに書くことになるかと思います。

例えば、以下のようなDOMがあったとします。

<div id="sample" data-hoge="hello"></div>

このDOMに対して、次のVueインスタンスをマウントすると、
このようになります。

new Vue({
  el: '#sample',
  template: '<div>Hello</div>',
  beforeMount(){
    console.log(this.$el) //<div id="sample" data-hoge="hello"></div>
    console.log(this.$el.dataset.hoge)//hello マウント前のelement要素にアクセス
  },
  mounted(){
    console.log(this.$el) // <div>Hello</div>
  }
})


mounted
上の説明と重複しますが、
mountedはマウント後に実行されるので、
templateにアクセスすることができます。

用途例としては、templateへの初期処理や、
ローディングの非表示処理などが挙げられるかと思います。

データの変更 / 画面の更新

いわゆる、画面が表示されている状態です。
このフェーズにおいては、
データが変更されると、render関数が実行され再描画が行われます。

この再描画の前後でそれぞれ、
beforeUpdateupdatedのフックが実行されます。

<フックの使いどころ例>
beforeUpdate
再描画前のDOMからの要素の取得処理などは、
ここで書きます。

Updated
そして、再描画したDOMに対しての初期処理などは、
ここで書きます。

インスタンスの破棄

インスタンスはv-if、v-forや、vue-routerなどで描画がされなくなるタイミングで、
破棄されます。
他にも、Vueインスタンスdestroy関数を実行しても破棄されます。

この破棄のタイミングの前後で実行されるフックが、
beforeDestroydestroyedです。

<フックの使いどころ例>
beforeDestroy
ここで書く処理として挙げられるのは、
Vueインスタンスの要素に別のインスタンスを紐付けたりした場合です。
紐付けしたインスタンスの破棄の処理をbeforeDestoryで行います。

destroyed
ここはインスタンスの破棄後に行う
TearDownの処理を書くことが多いです。

まとめ

Vueインスタンスのライフサイクルの概要を理解しておくと、
他のVueAPIの動きについて調べた時の理解を深めるのに役立つと思います。

正直、まだいくつかのフックについては、使いどきが掴めていないのもありますが、
今のうちに概要を掴めてよかったです。

【参考】
Vue インスタンス — Vue.js https://jp.vuejs.org/v2/guide/instance.html#%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%95%E3%83%83%E3%82%AF

vuejs2 - When to use the lifecycle method beforeMount in vue.js? - Stack Overflow