ライフサイクルフック

Options API を使う Vue 2 コンポーネントの生成・更新・破棄の流れを学ぶ。

Vue 2 のコンポーネントも、インスタンスの作成から DOM へのマウント、更新、破棄までのライフサイクルを持ちます。Options API では created や mounted のような option にメソッドを定義して、各段階の処理を登録します。

Vue 2 は既存システムで扱う機会があるため、現在の Vue 3 のフックとの違いを理解しながら、保守で必要な範囲を押さえることが重要です。

主なフックと使い分け

段階 フック 主な用途
インスタンス作成後 created data、computed、methods を使う初期化
DOM 反映後 mounted $refs、DOM、外部ライブラリの初期化
DOM 更新前後 beforeUpdate / updated 更新前後の DOM を扱う必要がある場合
破棄前後 beforeDestroy / destroyed 購読・タイマー・外部資源の後始末
KeepAlive の出入り activated / deactivated キャッシュされたコンポーネントの再表示・非表示
エラー errorCaptured 子孫コンポーネントで起きたエラーを捕捉する

created の時点では data のリアクティビティは利用できますが、コンポーネントの DOM はまだ利用できません。DOM や $refs が必要なら mounted を使います。

基本例: タイマーを管理する

開始したタイマーは、コンポーネントが消えても自動では停止しません。開始と破棄を対にして書きます。

export default {
  data() {
    return { elapsed: 0, timerId: null }
  },
  mounted() {
    this.timerId = window.setInterval(() => {
      this.elapsed += 1
    }, 1000)
  },
  beforeDestroy() {
    window.clearInterval(this.timerId)
  },
}

Vue 2 ではコンポーネントの data や methods に this でアクセスします。そのためライフサイクルフック自体をアロー関数にすると this が Vue インスタンスを指さず、期待通りに動きません。

更新フックの注意点

updated はリアクティブな値の変更による DOM 更新後に呼ばれます。ここで data を変更すると、さらに更新が起きて無限ループになる可能性があります。

  • 表示用の導出値には computed
  • 特定の値への反応には watch
  • 更新済みの DOM を読む必要がある場合だけ updated

DOM 更新の完了を待つだけなら、this.$nextTick() を使う方が意図に合うことがあります。更新フックは最後の手段として慎重に使います。

KeepAlive とエラー捕捉

<keep-alive> に囲まれたコンポーネントは、画面から切り替わってもすぐには破棄されません。この場合は destroyed ではなく deactivated が呼ばれ、再表示時には activated が呼ばれます。非表示中に止めたい処理は deactivated、完全に解放したい資源は beforeDestroy に置きます。

errorCaptured は子孫コンポーネントで発生したエラーを受け取るフックです。エラー通知や代替表示に使えますが、エラー表示自身が同じ失敗を繰り返さないよう注意します。未捕捉エラーをアプリ全体で扱う場合は、Vue のグローバルなエラーハンドラも確認します。

Vue 3 との対応

Vue 3 の Composition API では mounted は onMounted、beforeDestroy は onBeforeUnmount、destroyed は onUnmounted に対応します。Vue 2.7 には Composition API の一部もありますが、既存コードの Options API を Vue 3 と同じ前提で書き換えないことが大切です。

特に Vue 2 の破棄フック名は destroy で、Vue 3 の unmount とは異なります。移行や保守では、対象プロジェクトが実際に使う Vue のバージョンを確認してから API を選びましょう。

保守時のチェック

  • DOM 参照を created で行っていないか
  • 外部リスナー、タイマー、購読を beforeDestroy で解除しているか
  • updated で data を変更していないか
  • フック内の this が Vue インスタンスを指す書き方になっているか
  • <keep-alive> 内で destroyed が常に呼ばれると誤解していないか

ライフサイクルを理解すると、既存コンポーネントで「いつ初期化されたか」「なぜ画面を離れても処理が残るか」を追いやすくなります。

Sources