Can watch Api not traverse the shallowReactive Object deep?
What problem does this feature solve?
Watch Api will traverse the shallowReactive Object deep. I want to set the third party object (such as { [key as string]: Graph }
Graph is @antv/G6 Graph Object) to be ShallowReactive because i don't need it to be reactive deep. Even if these large objects are set to shallowReactive, they are still deep traverse in watch api. I think traverse the shallowReactive Object deep in watch api is not need because it improves performance.
Here is a demo that watch Api traverse the shallowReactive Object deep. https://codesandbox.io/s/vue3-watch-forked-6nj7j?file=/src/App.vue
I can use markRaw(object) to avoid traverse deep. But i think it can resolve in Vue when the obj is shallowReactive.
What does the proposed API look like?
add isShallowReactive
to traverse. If isShallowReactive true
, avoid to traverse deep.
export function traverse(value: unknown, seen?: Set<unknown>, isShallowReactive = true) {
// ...
else if (isPlainObject(value)) {
for (const key in value) {
!isShallow && traverse((value as any)[key], seen)
}
}
return value
}
or in traverse function, if the value is shallowReactive, avoid to traverse deep.
else if (isPlainObject(value)) {
const isShallow = isShallowReacitve(value)
for (const key in value) {
!isShallow && traverse((value as any)[key], seen)
}
}
return value
Deep watching is only possible on reactive data - watching relies on reactivity. So you are asking for the data in a shallowReactive
to be reactive. Then just use reactive
Apologies, I totally misread.
Thinking about this a bit, I think something like that has been discussed previously. One of the issues with this approach is that it would then miss reactive data nested within the nonreactive data of shallowReactive
:
const obj = shallowReactive({
foo: {
bar: ref(0)
}
})
In the above example, after your proposed change, a watch would no longer pick up on obj.foo.bar.value
being changed. That would technically be a breaking change which we can't introduce in the 3.* version range.
With markRaw
, you can control the behaviour right now, so that might be a good enough workaround/compromise?