为什么用 transform 做动画还是会卡顿?
我最近在 Vue 里做一个拖拽卡片的效果,为了性能特意用了 transform 来做位移,但快速拖动时还是明显掉帧。网上都说 transform 不会触发重排,应该很流畅才对,是不是我哪里写错了?
我试过把 will-change: transform 加上,也用了 requestAnimationFrame,但效果不明显。下面是我简化后的代码:
<template>
<div
class="card"
:style="{ transform: translate(${x}px, ${y}px) }"
@mousedown="startDrag"
>
拖我
</div>
</template>
难道是频繁更新响应式数据导致的?求指点!
虽然
transform本身不触发重排,性能很好,但你每次修改x和y,Vue 都要进行依赖收集、触发 Virtual DOM 的 diff 计算,甚至可能引发组件的局部重渲染。鼠标移动事件一秒触发几十上百次,Vue 的响应式开销累加起来就成了性能杀手。解决方案很简单:在拖动过程中,直接操作 DOM,绕过 Vue 的数据响应式系统。等拖动结束了,再同步数据状态。
试试这个改法:
这么改之后,拖动过程中完全绕过了 Vue 的更新机制,只走原生 DOM API,流畅度立马就不一样了。
will-change和requestAnimationFrame其实属于锦上添花,响应式数据频繁更新这个根本问题不解决,加再多优化手段也没用。