-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Component updating without computed property dep changing #1811
Comments
Note updating doesn't directly translate in HTML being patched. |
Yep, but it still needs a VDOM and lifecycle pass. I'm not reporting this as a bug as I think it's reasonable if the answer is this optimization is delegated to the VDOM. It seems possible to implement if you add some global state to track whether you're in the middle of derived data. |
This has to do with another optimization that prevents the computed getter from being over-eagerly evaluated too many times: const expensiveComputed = computed(() => {
return someArray.map(() => { ... })
})
for (let i = 0; i < 1000; i++) {
someArray.push({ ... })
} If computed getters are evaluated eagerly and synchronously, the above would result in the getter called 1000 times when in fact it needs to be called only once. So internally instead of calling the getter every time a dep changes, we simply mark the computed "dirty" and trigger effects that depend on it. The getter is then only called once, on demand, when the triggered effect accesses it. However, this means we can't know the new value at the time of mutation before triggering the effects, so we can't compare it to the old value to avoid unnecessary triggers. This is a trade-off that I don't know if is possible to "fix", but I think the current behavior is somewhat better because you can workaround it using a manual const computedCount = ref(0)
watchEffect(() => {
computedCount.value = Math.floor(count.value / 10)
}, { flush: 'sync' }) |
Thanks for the reply @yyx990803! This makes sense To avoid the case you describe, could the computed properties be marked dirty on dep set but updated on a tick, similar to reactive effects? Basically non-eager and async. If something reads before the delayed tick, it has the dirty flag. There is probably another tradeoff 😅 |
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 0
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 1
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 1
App.vue?3dfd:27 updated
App.vue?3dfd:22 computedCount updated 1
App.vue?3dfd:27 updated
|
This is fixed by d05c9a7 (will be out in 3.2) |
Reopen as this will be re-fixed in 3.4 by #5912. |
Fixed by #5912. |
What problem does this feature solve?
I'm relatively new to Vue. Learning about computed properties (cool feature!), I expected a component that has a computed dependency to only update when the computed value "changes" (wrt
hasChanged
) instead of updating whenever the recursive deps change.Here is a CodeSandbox example https://codesandbox.io/s/floral-pine-nvk0f?file=/src/App.vue
The
watch
does its ownhasChanged
check and updates only when thecomputedCount
changes (10x less thancount
). I expect the component to update at the same rate.A practical use case is ability to run a quicker timer update (say every 100ms) with the UI only rendering seconds (every 1s). Another example is only rendering only
user.name
but the underlyinguser
has irrelevant changes.You can create a separate component to add the change checking but it seems it could work in same component. I couldn't find a relevant issue. I can see the complexity tradeoff (needs external state when tracking read dependencies) but was wondering if that was the case.
What does the proposed API look like?
Same API but different component update behavior.
The text was updated successfully, but these errors were encountered: