vue.js 使用requestAnimationFrame时的转换组延迟

o7jaxewo  于 2022-11-17  发布在  Vue.js
关注(0)|答案(1)|浏览(222)

描述

我正在创建以下应用程序逻辑:

  • 有一个可检查的项目列表,每个项目都有一个特定的价格。
  • 勾选的项目会有计算的总价。

我还使用requestAnimationFrame动画显示了总价的数字变化。到目前为止一切都很好,数字动画本身工作得很好。

问题

但是,当我使用以下元素结构时,我的TransitionGroup移动转换开始滞后:

<Transition>
  <div>
    {{ animatedNumber }}
    <TransitionGroup>
      ...
    </TransitionGroup>
  </div>
</Transition>

备注

  • Transition元素和requestAnimationFrame之间似乎存在一些冲突。
  • 如果我删除Transition父元素,TransitionGroup移动动画将正常工作。
  • 如果我删除基于requestAnimationFrame的数字计数器,TransitionGroup移动动画工作正常。
  • 此问题仅在Chrome上发生。

演示
https://stackblitz.com/edit/vitejs-vite-a4hnef?file=src/components/App.vue

k3fezbri

k3fezbri1#

若要测试应用的性能,您可以按照以下步骤操作:

Open chrome dev tool -> performance -> click record -> make animation by checking to a checkbox -> click stop

结果应如下所示:

放大任务后,您将看到:

正如我们所看到的,每个任务都是由componentUpdateFn引起的。这是因为,在每个动画帧中,你都要更新变量并强制Vue重新渲染模板。这太麻烦了。为了让你的动画流畅,每个动画帧都应该在16ms的时间帧(60fps)内运行。
要解决此问题,应通过以下方法在每个动画帧中尽可能少地执行工作:

  • 优化animate函数
  • 如果您希望在每个帧中更新视图,您应该使用纯JS来完成,而不是使用Vue

这是你代码的optimal version。我只是用JS更新了动画的数字。它不完美,但它比原来的版本好得多。

// 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>

相关问题