【Vue.js】watch・watchEffectの違いと使い分け|リアクティブな監視処理の最適化

【Vue.js】watch・watchEffectの違いと使い分け|リアクティブな監視処理の最適化 Vue.js

Vue.js では、リアクティブな状態の変化を検知して処理を実行するために watchwatchEffect の2つの監視APIが用意されています。どちらも Vue 3 の Composition API において重要な役割を担いますが、それぞれ適した使い方があります。

この記事では、両者の違いや仕組み、パフォーマンス上の注意点を踏まえた使い分けについて解説します。

watch と watchEffect の基本的な違い

watch は「特定のリアクティブデータの変化」を明示的に監視するのに対し、watchEffect は「リアクティブな依存関係を自動的に収集して監視」します。

比較項目 watch watchEffect
監視対象 明示的(ref や computed など) 関数内で参照されたリアクティブ値すべて
実行タイミング 変更があったとき 即時実行+依存が変わるたび
用途 特定の変数に依存する処理 副作用のある処理(DOM変更・ログ・API)
クリーンアップ あり(第3引数でonCleanup) あり(戻り値に関数を返す)

watch の使い方と例

watch は複数の ref や reactive 値を個別に監視して処理を実行したい場合に適しています。


import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newVal, oldVal) => {
  console.log(`count が ${oldVal} から ${newVal} に変化しました`);
});

さらに、複数の ref を配列で監視することもできます。


watch([foo, bar], ([newFoo, newBar]) => {
  console.log('foo または bar が変わりました');
});

watchEffect の使い方と例

watchEffect は関数内で参照されたリアクティブな値を自動的にトラッキングします。初回実行+依存関係が変わるたびに再実行されます。


import { ref, watchEffect } from 'vue';

const message = ref('こんにちは');

watchEffect(() => {
  console.log(`現在のメッセージ: ${message.value}`);
});

依存関係の明示が不要なので、単純な副作用処理やAPI呼び出し、ログ出力に適しています。

クリーンアップ処理の違い

どちらも非同期処理や監視タイマーなどの「クリーンアップ」が必要なケースに対応可能です。

watch でのクリーンアップ


watch(source, (newVal, oldVal, onCleanup) => {
  const id = setInterval(() => { ... }, 1000);
  onCleanup(() => clearInterval(id));
});

watchEffect でのクリーンアップ


watchEffect((onCleanup) => {
  const id = setInterval(() => { ... }, 1000);
  onCleanup(() => clearInterval(id));
});

使い分けの指針

以下のようなルールを目安にするとよいでしょう。

  • 特定の値にのみ反応させたい → watch
  • 依存関係を気にせず自動追跡したい → watchEffect
  • 非同期や重い処理の最適化が必要 → watch(+オプション制御)

まとめ

watchwatchEffect はどちらもリアクティブな監視処理において強力なツールです。処理の性質や依存関係の明確さ、初回実行の有無などを考慮して適切に使い分けましょう。

Vue.js のリアクティビティの理解を深め、より効率的でバグの少ないコード設計を目指すうえで、これらの使いこなしは非常に重要です。