无法阻止 `touchmove` 在 iOS 上滚动 window

Can't prevent `touchmove` from scrolling window on iOS

我们试图在我们的 iOS 网络应用程序上滚动一个元素,同时阻止 window 本身滚动。我们正在捕获 window 上的 touchmove 事件,以编程方式滚动元素并(试图)通过在事件上调用 preventDefault 来防止 window 本身滚动。

遗憾的是,这在 Mobile Safari 中不起作用。 window 继续在我们的元素下方滚动。该问题听起来与 https://bugs.webkit.org/show_bug.cgi?id=163207 中描述的 Webkit 错误完全相同,但据推测该问题已在 iOS 10.3 中修复,而我是 运行 11.3.

捕获 touchforcestart 并调用 preventDefault 似乎确实阻止了 window 的滚动,但我们在 touchstart 中调用它,这似乎是 [=27] =] 因为 window 仍然滚动。只有在下次调用 touchstart 时才会阻止滚动。

对正在发生的事情有什么想法吗?我们很困惑,因为这显然是一个错误,但似乎已经在一段时间前修复了。

我最近 运行 遇到了同样的问题。注册 touchmove 事件侦听器时需要传递 { passive: false }。例如

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

这是因为文档触摸事件侦听器在 Safari 11.1 中默认是被动的,它与 iOS 11.3 捆绑在一起。此更改记录在 Safari 11.1 release notes:

Web APIs

  • [...]
  • Updated root document touch event listeners to use passive mode improving scrolling performance and reducing crashes.

您需要将 preventDefault 绑定到两个事件:touchmovetouchforcechange 以使其在 ios 11 中工作,例如

document.addEventListener('touchmove', this.preventDefault, {passive: false});
document.addEventListener('touchforcechange', this.preventDefault, {passive: false});

并且你应该在touchstart之前绑定它们

如果将它们绑定到 touchstartdragStart 处理程序中,它们只能防止在下一次拖动时滚动。

对我有用的是将 {passive:false} 选项传递给 addEventListener (explanation),并且您还需要确保在 [= 上执行 e.preventDefault() 14=] touchstart:

window.addEventListener("touchstart", e=>e.preventDefault(), {passive:false});
window.addEventListener("touchmove", e=>e.preventDefault(), {passive:false});