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が常に呼ばれると誤解していないか
ライフサイクルを理解すると、既存コンポーネントで「いつ初期化されたか」「なぜ画面を離れても処理が残るか」を追いやすくなります。