feat: add `pause/resume` methods for `render` function
fixed #5386
To address the issue of KeepAlive repeatedly executing the effect in the deactivate state, I have added pause and resume methods to ReactiveEffect for pausing and resuming the execution of the effect. Currently, it is used in the KeepAlive component. When the component is in the deactivated state, it pauses the execution of the effect and keeps track of whether it was called during the pause. When the component is in the activated state, it resumes the execution of the effect and immediately executes it once if the run function was called during the pause.
Size Report
Bundles
| File | Size | Gzip | Brotli |
|---|---|---|---|
| runtime-dom.global.prod.js | 86.8 kB (+349 B) | 33 kB (+112 B) | 29.8 kB (+77 B) |
| vue.global.prod.js | 133 kB (+349 B) | 49.8 kB (+129 B) | 44.6 kB (+85 B) |
Usages
| Name | Size | Gzip | Brotli |
|---|---|---|---|
| createApp | 48.3 kB (+283 B) | 19 kB (+89 B) | 17.3 kB (+73 B) |
| createSSRApp | 51.5 kB (+283 B) | 20.3 kB (+83 B) | 18.5 kB (+65 B) |
| defineCustomElement | 50.7 kB (+283 B) | 19.8 kB (+83 B) | 18 kB (+82 B) |
| overall | 61.7 kB (+349 B) | 23.9 kB (+127 B) | 21.7 kB (+147 B) |
Before:
Now:
This looks and sounds promising. Could you maybe elaborate on to what extend this is the same as what @BenceSzalai explained in https://github.com/vuejs/core/issues/5386#issuecomment-1449649119. I think this is what he calls 'level 5' right?
Also you mentioned in https://github.com/vuejs/core/issues/5386#issuecomment-1722910193 that it's more difficult to achieve for v-show. Does that mean that this PR doesn't solve it (yet) for components that are using the v-show attribute and were hidden at the time of navigating away?
The reason why v-show cannot be processed is because v-show is the data obtained during the update process. If we pause the execution of the effect, the element will never be re-displayed.
For computed and watch, we need access to the fn's return value when dealing with oldValue. During the pause period, the run function returns undefined, which can result in incorrect values for watch and computed. Therefore, the pause and resume functionality should be limited to the render function. I've introduced a derived class called RenderEffect to manage the execution of the render function.
Regarding the v-show directive, when it's bound to a component, it forces the child component to update along with the parent component's updates. However, v-show does not affect the rendering structure inside the component; it is solely used to control the display/hidden state of the component. Currently, this behavior causes the child component to be updated regardless of whether the component is in a visible state, which is not necessary under the v-show directive.
Related code: https://github.com/vuejs/core/blob/b8fc18c0b23be9a77b05dc41ed452a87a0becf82/packages/runtime-core/src/componentRenderUtils.ts#L340
Can someone take a look at this PR?
This feature allows me to use IntersectionObserver to control updates, which can significantly improve performance in the project.
Deploy Preview for vue-sfc-playground failed.
| Name | Link |
|---|---|
| Latest commit | a5446a3d5156ca44e9242a39d2252f7ef222558d |
| Latest deploy log | https://app.netlify.com/sites/vue-sfc-playground/deploys/652e9650c2d9d80008d8e07d |
@posva Sorry for bothering you, could you take a look at this PR?
I have added the pause/resume functionality to the ReactiveEffect class. As the ReactiveEffect class has a wide impact, I have opened a new PR #9651 to implement this feature.
@Alfred-Skyblue Besides Keep-Alive, I guess this is something that could also be applicable here?: https://github.com/vuejs/rfcs/discussions/501
@ferferga The functionality has temporarily shifted to be implemented in #9651. I noticed your mention in the RFC that state changes in internal components during the execution of a Transition animation would disrupt the animation state. Regarding the solution you proposed:
Stop dependency/effect tracking of the child component recursively.
Currently, we have implemented detachment for the scope of component instances in the EffectScope. Considering performance reasons, recursively pausing might lead to performance issues due to excessive depth. As of now, the solution I can think of is to manually call scope.pause during the animation execution and manually call scope.resume after the animation is completed. Of course, this approach may seem cumbersome.