Vue version 3.2 introduces a new Effect scope API. Use effectScope to create an effect scope, which can capture the reactive side effects (i.e. computed properties and listeners) created in it, so that the captured side effects can be processed together. The getCurrentScope method can be used to obtain the currently active effect scope. To register a handler callback function in the currently active effect scope, use onScopeDispose. This callback function is called when the associated effect scope is stopped.
const scope = effectScope() scope.run(() => { const doubled = computed(() => counter.value * 2) watch(doubled, () => console.log(doubled.value)) watchEffect(() => console.log('Count: ', doubled.value)) }) // 处理掉当前作用域内的所有 effect scope.stop()
In Vue's setup, the response will be collected at the beginning of initialization. When the instance is uninstalled, the response will be automatically untracked, which is a very convenient feature.
However, this can become very troublesome when we use it outside the component or write a separate package. How can I remove the reactive dependency on computed and watch in separate files?
Sample code, reference link
const disposables = [] const counter = ref(0) const doubled = computed(() => counter.value * 2) disposables.push(() => stop(doubled.effect)) const stopWatch2 = watchEffect(() => { console.log(`counter: ${counter.value}`) }) disposables.push(stopWatch2) const stopWatch3 = watch(doubled, () => { console.log(doubled.value) }) disposables.push(stopWatch3)
In the above code, we wrote a total of three responsive dependencies of computed & watch, and stored the stopHandle of these responsive dependencies in an array. , which means that we need to maintain this array so that when needed in the future, we can directly stop all responses as follows:
disposables.forEach((f) => f()) disposables = []
Especially when dealing with some complex combined function codes , manually collecting all reactive dependencies is tedious. If you don't have access to reactive dependencies created in composed functions, collecting them can easily be forgotten, which can lead to memory leaks and unexpected behavior.
This feature is an attempt to abstract the component's setup() responsive dependency collection and processing function into a more general API that can be reused outside the component model.
It also provides the ability to create "detached" effects from a component's setup() scope or a user-defined scope.
What problem does this function solve?
// global shared reactive state let foo function useFoo() { if (!foo) { // lazy initialization foo = ref() watch(foo, ...) // <- this is stopped when component that created it is unmounted // make some http calls etc } return foo } component1 = { setup() { useFoo() // lazily initialize } } component2 = { setup() { useFoo() // lazily initialize } }
I have a composed function that shares functionality between multiple components, the problem is when the first component called component1 stops the reactive dependency of useFoo. Since the ongoing effect on the global variable foo affects calls to other components, this effect needs to be stopped.
The above is the detailed content of How to use EffectScope in Vue3. For more information, please follow other related articles on the PHP Chinese website!