なぜフロントエンドのインタビューでは常にウォッチとコンピューテッドの違いについて尋ねられるのでしょうか?

この記事は初の公開アカウント「Front-end Dashie」です。フォローしてサプライズをゲットしてください~

最新のフロントエンド面接では、vue と React は基本的に面接プロセス中に質問する必要があるテクノロジー スタックです。Vue の応答性のトピックについて話すときは、watch和computed watchcomputed はどちらもデータの変更を監視するために使用されますが、実装原則、使用シナリオ、動作に大きな違いがあります。この記事では、 watchcomputed の原則と違いを詳しく説明し、面接プロセス中にいくつかの提案を提供します。

まず Vue 3 の応答性を理解する

Vue 3 は、基礎となるリアクティブ実装としてプロキシを使用して、オブジェクト プロパティの変更を監視し、対応する更新をトリガーします。データにアクセスすると、Vue は依存関係を確立し、データが変更されたときに関連する依存関係に通知して、ビューを更新します。これに関連して、基盤となるソース コードと watchcomputed の使用法の違いを詳しく調査します。

時計

watch オプションを使用すると、データの変更を監視し、カスタム操作を実行できます。通常、特定のデータの変更を監視し、非同期リクエスト、ログの印刷、アニメーションのトリガーなどの副作用を実行するために使用されます。 watch プロパティを作成すると、Vue は watch プロパティを監視するデータに関連付けるリアクティブな依存関係を確立します。監視対象のデータが変化すると、Vue は関連する watch プロパティに通知し、そのコールバック関数をトリガーします。このコールバック関数は新しい値と古い値をパラメータとして受け取り、必要な操作を実行できます。

ソースコード分析

相关文件:vue/src/runtime-core/apiWatch.tsvue/src/reactivity/src/effect.ts

Vue 3 のソース コードでは、watch の実装は主に createWatcher 関数と Watcher クラスに依存します。 。

  • createWatcher 関数は、Watcher インスタンスを作成
  • Watcher クラスは watch のコアであり、監視データへの依存関係を確立し、データが変更されたときにコールバック関数をトリガーします。
  • 内部Watcherでは、依存関係の追跡とコールバックのトリガーは Vue のリアクティブ システムを通じて実装されています。監視対象のデータが変更されると、Vue は依存関係を検出し、 Watcher のコールバックをトリガーします。
解釈

1. vue/src/runtime-core/apiWatch.ts では、watch 関数は次のように Watcher インスタンスを作成します。あ>

export function watch(
  source: WatchSource,
  cb: WatchCallback,
  options?: WatchOptions
): WatchStopHandle {
    
    
  // 创建一个watcher实例
  const watcher = new Watcher(vm, source, cb, {
    
    
    deep: options && options.deep,
    flush: options && options.flush,
    onTrack: options && options.onTrack,
    onTrigger: options && options.onTrigger,
  });
  // ...
}

このコードは Watcher インスタンスを作成します。vm は Vue インスタンス、source は監視対象のデータです、cb はコールバック関数とその他のオプションです。

2. Watcher的核心工作在vue/src/reactivity/src/effect.ts`。依存関係の追跡とコールバック トリガー ロジックが含まれています。簡略化した例を次に示します。

class Watcher {
  // ...

  get() {
    // 设置当前的watcher为活动watcher
    pushTarget(this);
    // 执行监视的数据,触发依赖项的收集
    const value = this.getter.call(this.vm, this.vm);
    // 恢复之前的watcher
    popTarget();
    return value;
  }

  update() {
    // 触发回调函数,通知数据变化
    this.run();
  }

  run() {
    // 执行回调函数
    const value = this.get();
    if (value !== this.value || isObject(value) || this.deep) {
      // 触发回调函数
      this.cb(value, this.value);
      this.value = value;
    }
  }

  // ...
}

このコードは、データを取得して依存関係の追跡をトリガーするための メソッドや、< a i= など、Watcher の重要な部分を示しています。 3> メソッドと メソッドは、コールバック関数をトリガーするために使用されます。 getupdaterun

時計の使用

<template>
  <div>
    <p>Count: {
   
   { count }}</p>
    <p>Doubled Count: {
   
   { doubledCount }}</p>
    <button @click="incrementCount">Increment Count</button>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

const count = ref(0);
const doubledCount = ref(0);

const incrementCount = () => {
  count.value++;
};

watch(count, (newVal, oldVal) => {
  // 监听 count 的变化
  doubledCount.value = newVal * 2;
});
</script>
</template>

この例では、<script setup> を使用して refwatch をインポートし、 のリアクティブ変数を作成します。 countdoubledCount。次に、 watch を使用して count の変更をリッスンし、 count が変更された場合に doubledCount を更新します。価値。

計算された

computed の動作は watch とは少し異なります。 computed他のリアクティブ データに依存する新しい計算プロパティの導出を可能にします。 computed プロパティを定義すると、Vue は計算されたプロパティをその依存関係に関連付ける依存関係を確立します。計算されたプロパティの値は、その依存関係が変更された場合にのみ再計算され、キャッシュされた結果は複数のアクセスにわたって返されます。これにより、不必要な計算が削減され、パフォーマンスが向上します。

ソースコード分析

Vue 3 のソース コードでは、computed の実装は主に createComputed 関数と ComputedRefImpl クラスに依存します。 。関連する部分はvue/src/reactivity/src/computed.tsファイルにあります。

  • createComputed 関数は、ComputedRefImpl インスタンスを作成
  • ComputedRefImpl クラスはcomputed のコアであり、計算関数をラップし、キャッシュ メカニズムを実装します。計算関数の実行と結果のキャッシュは、Vue の応答システムを通じて実装されます。
  • ComputedRefImplインスタンスは内部でキャッシュを維持し、依存するデータが変更されると、再計算してキャッシュを更新します。
解釈

1. vue/src/reactivity/src/computed.ts では、computed 関数は次のように ComputedRefImpl インスタンスを作成します。あ>

export function computed<T>(
  getter: ComputedGetter<T>,
  options?: ComputedOptions
): ComputedRef<T> {
  // 创建一个computed实例
  const c = new ComputedRefImpl(getter, options);
  // ...
  return c;
}

このコードは ComputedRefImpl インスタンスを作成します。getter は計算関数で、options にはいくつかのオプションが含まれます。

2、ComputedRefImpl の中心的な役割は、依存関係を追跡し、計算結果をキャッシュすることです。簡略化した例を次に示します。

class ComputedRefImpl<T> {
  // ...

  get value() {
    // 如果依赖项发生变化,或者值尚未计算
    if (this.dirty) {
      // 清除之前的依赖项
      cleanup(this);

      // 设置当前的computed属性为活动属性
      track(this);

      // 执行计算函数,获取新值
      this.value = this.effect();

      // 标记computed属性为已计算
      this.dirty = false;

      // 清理并设置新的依赖项
      stop(this);
    }

    // 返回缓存的值
    return this.value;
  }

  // ...
}

このコードはComputedRefImplのコア ワークフローを示しています。

  1. computed プロパティまたは関連する依存関係が初めて変更されると、computed プロパティは「ダーティ」(未計算)としてマークされます。
  2. が属性値を取得すると、valuegetter 関数がトリガーされます。
  3. プロパティ値を取得するとき、Vue は以前の依存関係をクリアし、新しい依存関係を再追跡します。
  4. 計算関数 (effect) が実行されて新しい値が取得されます。
  5. 新しい値はキャッシュされ、dirty フラグがfalse に設定され、計算されたことを示します。
  6. 新しい依存関係がクリーンアップされ、新しい依存関係が追跡されます。

このキャッシュ メカニズムによりcomputed、関連する依存関係が変更された場合にのみ属性の値が再計算されるようになり、パフォーマンスが向上し、不必要な計算が削減されます。

計算された使用

<template>
  <div>
    <p>Count: {
   
   { count }}</p>
    <p>Doubled Count: {
   
   { doubledCount }}</p>
    <button @click="incrementCount">Increment Count</button>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const count = ref(0);

const doubledCount = computed(() => {
  // 计算属性,依赖于 count
  return count.value * 2;
});

const incrementCount = () => {
  count.value++;
};
</script>
</template>

この例では、<script setup> を使用して refcomputed をインポートし、 リアクティブ変数を作成します。 >countdoubledCount。次に、 computed を使用して、 の値に依存する計算プロパティ doubledCount を作成します。 count

違いと使用シナリオ

上記 2 つの原理と使用法を紹介しました。watchcomputed の主な違いと、それらが使用するシーンをまとめてみましょう。使用済み。

違い

  1. 响应方式
    • watchデータの変更を監視するために使用され、副作用を実行できるようになります。
    • computed依存関係の変更に基づいて値が変化する新しい計算プロパティを導出するために使用されます。
  2. 缓存
    • watch結果はキャッシュされず、データが変更されるたびにコールバックがトリガーされます。
    • computed計算結果はキャッシュされ、依存関係が変更された場合にのみ再計算されます。

使用するシーン

  1. 時計の使用シナリオ:

    • 非同期操作: ネットワーク要求の送信など、データ変更時に非同期操作を実行する必要がある場合。
    • 副作用: ログ記録やアニメーションのトリガーなど、データ変更に関連する一部の操作を実行します。
    • 複数のデータ変更を監視し、さまざまな操作を実行します。
  2. 計算された使用シナリオ:

    • 派生プロパティ: テンプレートで使用するために既存のデータから新しいプロパティを派生する必要がある場合。
    • 二重計算を避ける: 計算に負荷がかかるが、その依存関係が頻繁に変更されない場合は、computed を使用して不必要な計算を回避します。

面接のアドバイス

面接官は、Vue のリアクティブ システムについての理解を理解するために、watchcomputed に関する質問をすることがよくあります。ここでは、皆様のお役に立つヒントをいくつか紹介します。

  1. 原則を理解する: watchcomputed がどのように機能するか、またそれらが Vue のリアクティブとどのように関連するかを必ず理解してください。システム関係。
  2. 使用例: watchcomputed をいつどのように使用するかについて明確な例を提供できるようにします。
  3. 違いと使用シナリオ: watchcomputed の違いと、どちらを選択すべきかを強調します。使用シナリオは 1 つです。
  4. パフォーマンスに関する考慮事項: パフォーマンスに関する質問に答えるときは、不必要な計算を回避してパフォーマンスを向上させるのにどのように役立つかを説明できるようにしてくださいcomputed
  5. デモ体験: 実際のプロジェクトで watchcomputed を使用した経験と成功事例を共有してください。面接官はあなたの実際のスキルをよりよく理解できます。

学習教材の共有

フロントエンド兄弟 Dashi をフォローし、公式アカウント「Learning Resources」に返信して無料で入手してください~

フロントエンド兄弟 Dashi をフォローし、公式アカウント「Learning Resources」に返信して無料で入手してください~

この記事はmdnice複数のプラットフォームで公開されています。

おすすめ

転載: blog.csdn.net/yuleiming21/article/details/133997217