移动端 touchmove 监听加了 passive 为啥还是卡顿?
我在做移动端的滑动组件,给 touchmove 事件加了 { passive: true },但页面滚动还是明显卡顿,是不是我用错了?
之前没加 passive 的时候 Chrome 控制台有警告,加了之后警告没了,但性能没提升。代码是这样写的:
element.addEventListener('touchmove', (e) => {
// 这里只是记录滑动位置,没调用 preventDefault
this.updatePosition(e.touches[0].pageX, e.touches[0].pageY);
}, { passive: true });
难道 passive 真的不能提升滚动流畅度?还是我漏了什么设置?
首先,确保 updatePosition 函数内部没有耗时操作。即使你没有调用 preventDefault,如果 JavaScript 执行时间过长,也会导致卡顿。
其次,检查一下是否有其他 touchmove 事件监听器在干扰。有时候多个事件监听器叠加在一起会导致性能问题。
最后,可以尝试减少 DOM 操作或者使用 requestAnimationFrame 来优化动画。这样更清晰。
举个例子,你可以这样改写你的 updatePosition 方法:
pre class="pure-highlightjs line-numbers">
let lastTouchPosition = null;
function updatePosition(x, y) {
lastTouchPosition = { x, y };
}
function animate() {
if (lastTouchPosition) {
// 在这里更新你的 DOM 或者进行其他渲染操作
console.log(lastTouchPosition);
lastTouchPosition = null;
}
requestAnimationFrame(animate);
}
animate();
element.addEventListener('touchmove', (e) => {
updatePosition(e.touches[0].pageX, e.touches[0].pageY);
}, { passive: true });
这样把 DOM 操作移到了 requestAnimationFrame 中,可以提高流畅度。希望这些能帮到你。
第一,你的
updatePosition里面是不是有重操作?比如频繁读写DOM或者复杂计算?这个回调即使不阻塞滚动,本身执行时间太长照样会卡。建议用console.time测下这个函数耗时。第二,更隐蔽的坑:检查CSS里有没有用
transform或will-change开启硬件加速。我之前傻乎乎地加了passive但没开GPU加速,效果跟没加一样。试试这样:最后,如果还卡,建议上
requestAnimationFrame来优化执行时机:这几个组合拳打下来,我这边滑动帧率直接从40fps飙到55+。如果还不行,可能要考虑换IntersectionObserver之类的方案了。