移动端滚动卡顿时,怎么用Passive监听优化事件?

毓金酱~ 阅读 23

在优化移动端页面时,我给触摸事件加了{ passive: true },滚动确实流畅了,但有个问题:touchMove里调用event.preventDefault()阻止滚动时完全没反应了,这是为什么呢?

具体场景是这样的,页面里有个侧边栏拖拽组件,当手指滑动到侧边栏区域时,需要阻止页面滚动,只触发拖拽。我之前写的是:


document.addEventListener('touchmove', (event) => {
  if (isDragging) event.preventDefault()
}, { passive: true })

但这样设置后拖拽失效了,控制台还报错:The 'passive' option must be used in a function with 'Capture' phase。尝试把passive: false又回到卡顿状态…

试过分开写两个事件监听,但感觉这样代码重复了,有没有更好的处理方式?

我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
程序猿婷婷
passive: true 的时候不能调用 preventDefault(),这是浏览器限制。改成这样:

document.addEventListener('touchstart', (event) => {
if (isDraggingArea(event.target)) {
// 在 capture 阶段就决定是否阻止默认行为
document.addEventListener('touchmove', preventScroll, { passive: false })
}
}, { capture: true })

function preventScroll(e) {
if (isDragging) e.preventDefault()
}

// 拖拽结束记得解绑
document.removeEventListener('touchmove', preventScroll)


核心就是:只有非 passive 的事件才能阻止滚动,而且要在 capture 阶段提前注册。
点赞 5
2026-02-12 11:04
司徒文鑫
passive: true 的时候不能调用 preventDefault(),这是浏览器限制。你得分开监听,一个带 passive 优化滚动,另一个不带 passive 专门处理拖拽阻止默认行为。

我之前这样搞的:

document.addEventListener('touchstart', () => {
isDragging = true
})

document.addEventListener('touchmove', (event) => {
if (isDragging) {
event.preventDefault()
}
}, { passive: false })


确保只有需要阻止滚动的时候才在非 passive 的 listener 里处理,其他滚动交给 passive 提升性能。
点赞 4
2026-02-09 05:00