Welcome to Aaron Blog! en and jp version is now updating! 🎉

Watch と Computed

Watch と Computed の違いを探り、ソースコードを深掘り

Loading comments...

Watch と Computed、どちらが速い?

最近、友人が面接でこの質問をされたそうで、とても面白かったので、Vue のソースコードをしっかり調べて、両者の違いとパフォーマンスを見てみようと思いました!

まずは Vue のリアクティブシステムを理解しよう

比較を始める前に、Vue のリアクティブシステムがどう機能しているかを知る必要があります。Vue 3 では Proxy を使ってデータの変更を監視し、変更があると自動的に画面が更新されます。

Proxy はオブジェクトの getset をフックします。以下は公式サイトの簡易実装:

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
    }
  })
}

重要な概念:

  • track:このプロパティを使っている依存元を記録する
  • trigger:プロパティが変更されたとき、依存元を通知して更新させる

ソースコードでも同様に tracktrigger が使われています:

reactiveProxy Handler

Watch とは?

Watch は特定のデータの変化を監視し、変化があった際に指定したコールバックを実行する関数です。

特徴:

  • ref/reactive 関数/オブジェクトなどを監視できる
  • コールバック関数に新旧の値が渡される
  • 副作用(API 呼び出しなど)に最適

ソースコードの要点(抜粋):

effect = new ReactiveEffect(getter) // 変化があればコールバックを実行

Computed とは?

Computed は既存のデータから新しい値を「計算」する仕組みです。結果はキャッシュされ、依存が変更されたときのみ再計算されます。

特徴:

  • 値にアクセスするまで再計算しない(遅延評価)
  • キャッシュ機能がある
  • 計算結果が複数箇所で使われるときに最適

ソースコードの要点:

this.flags |= EffectFlags.DIRTY // 変更時は dirty フラグを立てるだけ
refreshComputed(this) // アクセス時に dirty 状態を確認し再計算するか判断

Watch vs Computed 比較

特徴ComputedWatch
目的新しい値の計算副作用の実行
戻り値ありなし
キャッシュありなし
実行タイミングアクセス時に計算変化時に即実行
副作用推奨されない推奨される
非同期処理不向き向いている
コードスタイル宣言的命令的
パフォーマンス自動的に高効率最適化は開発者次第

どちらが速い?

結論:通常は Computed の方が高速 理由:

  • 計算結果をキャッシュしている
  • 実際にアクセスされたときだけ再計算される

一方、Watch は毎回コールバックを実行します。つまり:

  • 多くの場面で再利用される計算結果 → Computed が有利
  • 副作用や API 呼び出しが必要 → Watch が適任

まとめ:ベストプラクティス

  • 値を計算したいとき → まず Computed を使う
  • 副作用(非同期処理など)が必要 → Watch を使う

Vue の設計哲学にもある通り、「宣言的な書き方(Computed)」を基本に、必要に応じて「命令的な書き方(Watch)」を使うのが理想です。

Loading comments...