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
watch
The 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.ts
和vue/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.
createWatcher
The function is responsible for creating theWatcher
instance and receiving monitored data, callback functions, and other options.Watcher
The class is the core ofwatch
, which establishes a dependency on monitoring data and triggers a callback function when the data changes.- Internally
Watcher
, 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 ofWatcher
.
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. update
run
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
. computed
Allows 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.ts
file.
createComputed
The function is responsible for creating theComputedRefImpl
instance and receiving calculation functions and other options.ComputedRefImpl
The 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.ComputedRefImpl
The 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:
- When the
computed
property or related dependencies are changed for the first time, thecomputed
property will be marked as "dirty" (uncalculated). - When gets the attribute value,
value
’sgetter
function will be triggered. - When getting a property value, Vue clears the previous dependency and then re-tracks the new dependency.
- The calculation function (
effect
) will be executed to obtain the new value. - The new value will be cached, and the
dirty
flag will be set tofalse
, indicating that it has been calculated. - 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 doubledCount
computed
doubledCount
count
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
- Gakuen method:
watch
Used to monitor changes in data, it allows you to perform side effects.computed
Used to derive a new computed property whose value changes based on changes in dependencies.
- 缓存:
watch
The results will not be cached, and a callback will be triggered every time the data changes.computed
Calculation results are cached and recalculated only when dependencies change.
scenes to be used
-
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.
-
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, use
computed
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:
- Understand the principles: Make sure you understand how
watch
andcomputed
work and how they relate to Vue’s reactive system Relationship. - Usage Examples: Be able to provide clear examples of how and when to use
watch
andcomputed
they. - Differences and usage scenarios: Highlight the differences between
watch
andcomputed
and when to choose one over the other One usage scenario. - Performance considerations: When answering questions about performance, be able to explain
computed
how it can help avoid unnecessary calculations and improve performance. - Demonstration experience: Share your experience and success stories of using
watch
andcomputed
in actual projects. This gives the interviewer a better understanding of your actual skills.
Learning material sharing
This article is published bymdniceMultiple platforms