移动端 touchmove 监听加了 passive 为啥还是卡顿?

Zz珍珍 阅读 12

我在做移动端的滑动组件,给 touchmove 事件加了 { passive: true },但页面滚动还是明显卡顿,是不是我用错了?

之前没加 passive 的时候 Chrome 控制台有警告,加了之后警告没了,但性能没提升。代码是这样写的:

element.addEventListener('touchmove', (e) => {
  // 这里只是记录滑动位置,没调用 preventDefault
  this.updatePosition(e.touches[0].pageX, e.touches[0].pageY);
}, { passive: true });

难道 passive 真的不能提升滚动流畅度?还是我漏了什么设置?

我来解答 赞 7 收藏
二维码
手机扫码查看
1 条解答
令狐冠英
哈,这个问题我也踩过坑!passive确实能减少主线程阻塞,但光加这个还不够。血泪教训告诉我两个关键点:

第一,你的updatePosition里面是不是有重操作?比如频繁读写DOM或者复杂计算?这个回调即使不阻塞滚动,本身执行时间太长照样会卡。建议用console.time测下这个函数耗时。

第二,更隐蔽的坑:检查CSS里有没有用transformwill-change开启硬件加速。我之前傻乎乎地加了passive但没开GPU加速,效果跟没加一样。试试这样:

.your-element {
transform: translateZ(0);
will-change: transform;
}


最后,如果还卡,建议上requestAnimationFrame来优化执行时机:

let ticking = false;
element.addEventListener('touchmove', (e) => {
if (!ticking) {
requestAnimationFrame(() => {
this.updatePosition(e.touches[0].pageX, e.touches[0].pageY);
ticking = false;
});
ticking = true;
}
}, { passive: true });


这几个组合拳打下来,我这边滑动帧率直接从40fps飙到55+。如果还不行,可能要考虑换IntersectionObserver之类的方案了。
点赞
2026-03-09 12:01