will-change 设置后反而卡顿了?是我用错了吗?

Air-怡涵 阅读 42

我在做一个拖拽动画,给元素加了 will-change: transform 想提升性能,结果页面更卡了,甚至内存占用飙升。是不是滥用 will-change 会适得其反?

我是在 mousemove 事件里动态设置的,代码大概这样:

element.addEventListener('mousemove', () => {
  element.style.willChange = 'transform';
  element.style.transform = <code>translateX(${x}px)</code>;
});

是不是应该提前设置,而不是在频繁触发的事件里动态加?求指点!

我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
Des.婉琳
嗯,这个问题挺常见的。will-change 设置不当确实会导致性能问题。你每次 mousemove 都设置 will-change,这会频繁触发浏览器的重排,性能肯定拉跨。你应该提前设置 will-change,然后在动画结束后再移除。改一下就行:

element.addEventListener('mousedown', () => {
element.style.willChange = 'transform';
});

element.addEventListener('mousemove', (event) => {
const x = event.clientX;
element.style.transform = translateX(${x}px);
});

element.addEventListener('mouseup', () => {
element.style.willChange = 'auto';
});


这样鼠标按下时才设置 will-change,移动时只更新 transform,鼠标抬起后再取消 will-change,性能应该会好很多。
点赞
2026-03-25 03:03
富水~
富水~ Lv1
你用错地方了!will-change 确实不能这么玩,在 mousemove 里动态设置反而会帮倒忙。

浏览器在检测到 will-change 后会为元素创建独立的合成层,这个过程是有开销的。你在每次 mousemove 时都设置,相当于频繁触发层的创建和销毁,内存当然飙升,而且这波操作本身就消耗性能。

正确做法是:提前设置,动画结束再移除。

比如拖拽开始前加上:

element.style.willChange = 'transform';

然后在拖拽结束后(mouseup)及时清掉:

element.style.willChange = 'auto';

或者用完动画后加个 setTimeout 延迟清理也行:

setTimeout(() => {
element.style.willChange = 'auto';
}, 500);

另外提醒一下,transform 用 inline 样式在 mousemove 里频繁更新本身也不是最优方案。如果卡顿明显,可以考虑用 requestAnimationFrame 来节流,或者直接用 CSS transition/animation 把变化写在 class 里,JS 只负责切换 class,这样性能会好很多。

will-change 是个好东西,但得用在刀刃上——动画开始前声明,结束后收回,别让它一直占着不放。
点赞
2026-03-11 23:20