will-change 设置后反而卡顿了?是我用错了吗?
我在做一个拖拽动画,给元素加了 will-change: transform 想提升性能,结果页面更卡了,甚至内存占用飙升。是不是滥用 will-change 会适得其反?
我是在 mousemove 事件里动态设置的,代码大概这样:
element.addEventListener('mousemove', () => {
element.style.willChange = 'transform';
element.style.transform = <code>translateX(${x}px)</code>;
});
是不是应该提前设置,而不是在频繁触发的事件里动态加?求指点!
浏览器在检测到 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 是个好东西,但得用在刀刃上——动画开始前声明,结束后收回,别让它一直占着不放。