Why do front-end interviews always ask about the difference between watch and computed?

This article is the first public account "Front-end Dashie", follow it and get surprises~

In modern front-end interviews, vue and react are the technology stacks that are basically required to be asked during the interview process. When talking about the topic of Vue responsiveness,watch和computed the interviewer likes it very much. Although watch and computed are both used to monitor changes in data, they have significant differences in implementation principles, usage scenarios, and behaviors. This article will delve into the principles and differences between watch and computed, and provide some suggestions during the interview process.

First understand Vue 3 responsiveness

Vue 3 uses Proxy as its underlying reactive implementation to monitor changes in object properties and trigger corresponding updates. When you access data, Vue establishes a dependency and then notifies the relevant dependencies when the data changes, thus updating the view. In this context, we deeply explore the differences in the underlying source code and usage of watch and computed.

Watch

watchThe option allows you to monitor data changes and perform custom operations. It is usually used to monitor changes in certain data and perform side effects, such as asynchronous requests, printing logs, or triggering animations. When you create a watch property, Vue will establish a reactive dependency that associates the watch property to the data you want to monitor. When the monitored data changes, Vue will notify the relevant watch properties and trigger its callback function. This callback function will receive the new value and the old value as parameters, where you can perform the required operations.

Source code analysis

Sokan sentence item:vue/src/runtime-core/apiWatch.tsvue/src/reactivity/src/effect.ts.

In the source code of Vue 3, the implementation of watch mainly depends on the createWatcher function and Watcher class.

  • createWatcherThe function is responsible for creating the Watcher instance and receiving monitored data, callback functions, and other options.
  • WatcherThe class is the core of watch, which establishes a dependency on monitoring data and triggers a callback function when the data changes.
  • InternallyWatcher, dependency tracking and callback triggering are implemented through Vue's reactive system. When the monitored data changes, Vue will detect the dependency and trigger the callback of Watcher.
Interpretation

1. In vue/src/runtime-core/apiWatch.ts, the watch function is responsible for creating the Watcher instance, as follows:

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,
  });
  // ...
}

This code creates an Watcher instance, where vm is the Vue instance and source is the data to be monitored , cb is the callback function, and other options.

2. Watcher的核心工作在vue/src/reactivity/src/effect.ts`, which contains dependency tracking and callback triggering logic. Here's a simplified example:

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;
    }
  }

  // ...
}

This code shows the key parts of Watcher, including get methods for getting data and triggering dependency tracking, and < The a i=3> and methods are used to trigger the callback function. updaterun

watch use

<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>

In this example, we use <script setup> to import ref and watch and create Reactive variables for count and doubledCount. Then, we use watch to listen for changes in count and update when count changes. value. doubledCount

Computed

computed works a little differently than watch. computedAllows the derivation of a new computed property that depends on other reactive data. When you define a computed property, Vue will establish a dependency relationship that associates the calculated property to its dependencies. The value of a computed property is only recalculated when its dependencies change, and cached results are returned across multiple accesses. This reduces unnecessary calculations and improves performance.

Source code analysis

In the source code of Vue 3, the implementation of computed mainly depends on the createComputed function and ComputedRefImpl class. The relevant parts are in thevue/src/reactivity/src/computed.tsfile.

  • createComputedThe function is responsible for creating the ComputedRefImpl instance and receiving calculation functions and other options.
  • ComputedRefImplThe class is the core ofcomputed, which wraps calculation functions and implements the caching mechanism. The execution of calculation functions and the caching of results are implemented through Vue's responsive system.
  • ComputedRefImplThe instance maintains a cache internally, and when dependent data changes, it recalculates and updates the cache.
Interpretation

1. In vue/src/reactivity/src/computed.ts, the computed function is responsible for creating the ComputedRefImpl instance, as follows:

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

This code creates an ComputedRefImpl instance, where getter is the calculation function and options contains some options.

The core job of 2, ComputedRefImpl is to track dependencies and cache calculation results. Here's a simplified example:

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;
  }

  // ...
}

This code showsComputedRefImpl’s core workflow:

  1. When the computed property or related dependencies are changed for the first time, the computed property will be marked as "dirty" (uncalculated).
  2. When gets the attribute value, value’s getter function will be triggered.
  3. When getting a property value, Vue clears the previous dependency and then re-tracks the new dependency.
  4. The calculation function (effect) will be executed to obtain the new value.
  5. The new value will be cached, and the dirty flag will be set tofalse, indicating that it has been calculated.
  6. New dependencies will be cleaned up and new dependencies will be tracked.

This caching mechanism ensurescomputed that the value of the attribute is only recalculated when the relevant dependencies change, improving performance and reducing unnecessary calculations.

Computed use

<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>

In this example, we also use <script setup> to import ref and computed and create . that depends on the value of to create a computed property . We then use count and doubledCountcomputeddoubledCountcount

Differences and usage scenarios

We have introduced the principles and usage of the two above. Let us summarize the main differences between watch and computed as well as their scenes to be used.

the difference

  1. Gakuen method:
    • watchUsed to monitor changes in data, it allows you to perform side effects.
    • computedUsed to derive a new computed property whose value changes based on changes in dependencies.
  2. 缓存
    • watchThe results will not be cached, and a callback will be triggered every time the data changes.
    • computedCalculation results are cached and recalculated only when dependencies change.

scenes to be used

  1. Usage scenarios of watch:

    • Asynchronous operations: When you need to perform asynchronous operations when data changes, such as sending network requests.
    • Side effects: Perform some operations related to data changes, such as logging or triggering animations.
    • Monitor multiple data changes and perform different operations.
  2. Computed usage scenarios:

    • Derived properties: When you need to derive new properties from existing data for use in templates.
    • Avoid double calculations: When a calculation is expensive but its dependencies don't change often, usecomputed to avoid unnecessary calculations.

Interview advice

Interviewers often ask questions about watch and computed to understand your understanding of Vue's reactive system. Here are some tips that I hope will be helpful to you:

  1. Understand the principles: Make sure you understand how watch and computed work and how they relate to Vue’s reactive system Relationship.
  2. Usage Examples: Be able to provide clear examples of how and when to use watch and computed they.
  3. Differences and usage scenarios: Highlight the differences between watch and computed and when to choose one over the other One usage scenario.
  4. Performance considerations: When answering questions about performance, be able to explaincomputed how it can help avoid unnecessary calculations and improve performance.
  5. Demonstration experience: Share your experience and success stories of using watch and computed in actual projects. This gives the interviewer a better understanding of your actual skills.

Learning material sharing

Follow the front-end brother Dashi, and reply to the official account "Learning Resources" to get it for free~

Follow the front-end brother Dashi, and reply to the official account "Learning Resources" to get it for free~

This article is published bymdniceMultiple platforms

Guess you like

Origin blog.csdn.net/yuleiming21/article/details/133997217