Description
I'm creating the following app logic:
- There is a list of checkable items with a specific price for each.
- There is a calculated total price for checked items.
I'm also animating the number change for the total price using the requestAnimationFrame
.
So far so good, the number animation itself works fine.
Problem
However, my TransitionGroup
move transition starts to lag when I have the following element structure:
<Transition>
<div>
{{ animatedNumber }}
<TransitionGroup>
...
</TransitionGroup>
</div>
</Transition>
Notes
- Seems that there is some conflict between the
Transition
elements andrequestAnimationFrame
. - The
TransitionGroup
move animation works fine if I remove the parentTransition
element. - The
TransitionGroup
move animation works fine if I remove the number counter based onrequestAnimationFrame
. - This issue happens only on Chrome.
Demo
Zooming into a task you will see:
As we can see each task is caused by the componentUpdateFn
. That is because, in every animation frame, you update the variable and force Vue to re-render the template. It's too much work. To make your animation smooth, each animation frame should run in a 16ms time frame (60fps)
To solve your problem you should put in less work as possible in each animation frame by:
- optimizing your
animate
function - if you want to update your view in every frame, you should do it by pure JS instead of using Vue
This is the optimal version of your code. I just use JS to update the animating number. It's not perfect but it much better than the original version.
// in the script. update the view by pure JS
watch(animatedTotalPrice, () => {
totalPriceElm.value.innerText = animatedTotalPrice.value;
});
// in the template, DON'T let Vue do the updating work
<h3 ref="totalPriceElm" v-once>{{ animatedTotalPrice }} USD</h3>