Lighthouse 报“使用被动监听器”问题该怎么解决?

W″阳阳 阅读 4

我在用 Lighthouse 跑性能检测时,Best Practices 里一直提示“Uses passive event listeners to improve scrolling performance”,但我不太明白具体要改哪里。我确实给 touchstart 加了 preventDefault(),因为要做滑动判断,但好像这会影响滚动性能?

这是我的一段事件绑定代码:

document.addEventListener('touchstart', function(e) {
  if (shouldPreventSwipe()) {
    e.preventDefault();
  }
}, { passive: false });

如果改成 passive: true,preventDefault 就会报错。有没有办法既保留逻辑又通过 Lighthouse 检查?

我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
彦杰 ☘︎
这个问题其实有个很优雅的解法:把 preventDefault 从 touchstart 移到 touchmove,同时用 CSS 的 touch-action 属性配合。

核心思路是这样的:你现在在 touchstart 就判断是否要阻止滑动,但更合理的做法是用 CSS 告诉浏览器“这里不需要滚动处理”,然后在 touchmove 里做你的滑动判断。

/ 需要阻止默认滚动的元素上加这个 /
.your-element {
touch-action: none;
}


然后 JS 部分改成这样:

document.addEventListener('touchmove', function(e) {
if (shouldPreventSwipe()) {
e.preventDefault();
}
}, { passive: false });


为什么这么改:

touch-action: none 会直接禁止浏览器处理滚动,等于在浏览器层面先拦截了。然后你在 touchmove 里判断是否要阻止滑动行为,这样 Lighthouse 也不会再报错了,因为 touchmove 本身就不是滚动性能的关键路径。

如果你觉得 touchmove 每个滑动都会触发判断有点重,还可以再优化成:

let startX, startY;

document.addEventListener('touchstart', function(e) {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
}, { passive: true }); // 这里用 passive: true 没问题

document.addEventListener('touchmove', function(e) {
if (shouldPreventSwipe()) {
e.preventDefault();
}
}, { passive: false });


把判断逻辑拆到 touchmove,touchstart 只记录起始位置,这样既满足你的业务需求,又符合性能最佳实践。
点赞
2026-03-13 11:29