Most of the time, we use watch to explicitly specify dependencies to avoid unnecessary duplicate triggers, and avoid accidentally introducing new dependencies during subsequent code modification or reconstruction. watchEffect is suitable for some scenarios where logic is relatively simple and depend on sources and logic is strongly related.
You can think that they are two different forms of the same function, and the underlying implementation is the same.
- watch- explicitly specifies the dependency source, and executes callback functions when the dependency source is updated
- watchEffect - Automatically collect dependent sources, and re-execute themselves when dependent sources are updated
Responsive dependency collection
First of all, you need to understand how the responsiveness of vue 3 works. I think many articles have discussed this part in detail, so I will briefly introduce it here. Here is a simplified version of the ref implementation:
const ref = (initialValue) => { let _value = initialValue return { get value() { track(this, 'value') // Collect dependencies return _value }, set value() { _value = value trigger(this, 'value') // Trigger dependency } } }
When accessing data, the track is called and the accessed fields are recorded. When writing data, trigger is called and triggered to update the event bound to this field that it previously relies on (i.e. effect - computed, watch, watchEffect are all effect). They will be recorded in a global WeakMap, and will not be expanded here. If you are interested, you can look at the source code.
const counter = ref(1) () // `track()` is called = 2 // `trigger()` Being called
When we need dependencies in a function, we only need to record the number of times track() is called (and the corresponding object and field) during the function execution. For example:
const counter = ref(1)function foo() { () }function collectDeps() { startTracking() foo() // In this process, counter is collected stopTracking() }
In this way, you can know that the function foo depends on counter.
Watch
A generalised watch api should be like this (others that directly accept ref or reactive as parameters are actually sugar).
watch( () => { /* Depend on source collection function */ }, () => { /* Callback function when dependent source changes */ } )
The dependency source function here will only be executed once, and the callback function will be triggered every time the dependency source changes, but the callback function does not dependency collection. In other words, there is no need to be a direct relationship between the dependency source and the callback function.
WatchEffect
watchEffect is equivalent to merging the watch's dependency source and callback function. When any responsive dependencies you use are updated, the callback function will be executed again.
Unlike watch, the callback function of watchEffect will be executed immediately (i.e. { immediate: true }).
watchEffect( () => { /* The dependency source is also a callback function */ } )
The following two usages are basically equivalent in behavior:
watchEffect( () => () ) watch( () => , () => (), { immediate: true } )
The difference from watch is that in watchEffect, the dependency source will be executed repeatedly, and dynamic newly added dependencies will be collected, for example:
const counter = ref(0)const enabled = ref(false) watchEffect(() => { if () () })// (Ignore the following nextTick)// watchEffect Will be executed immediately,because “enabled“ for false, Only collected at this time “enabled“ rely += 1 // No response = true // Effect trigger,Console out "1" += 1 // “counter“ 被作for新的rely被收集,Console out "2" = false // The function is re-execute,No output += 1 // The function is re-execute,No output (Although counter No use anymore,但是作forrely还是会trigger函数)
By the way, computed is actually similar to a synchronous version of watchEffect with output.
When to use what?
It is recommended to use watch to explicitly specify dependencies most of the time to avoid unnecessary duplicate triggers, and to avoid accidentally introducing new dependencies during subsequent code modification or reconstruction. watchEffect is suitable for some scenarios where logic is relatively simple and depend on source and logic strongly related (or lazy scenarios).
Here is the article about what is the difference between watch and watchEffect in Vue3? That’s all for the article. For more related contents in Vue3, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!