无法阻止“touchmove”在 iOS 上滚动窗口

Posted

技术标签:

【中文标题】无法阻止“touchmove”在 iOS 上滚动窗口【英文标题】:Can't prevent `touchmove` from scrolling window on iOS 【发布时间】:2018-09-05 02:55:37 【问题描述】:

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

很遗憾,这在 Mobile Safari 中不起作用。窗口继续在我们的元素下方滚动。这个问题听起来与https://bugs.webkit.org/show_bug.cgi?id=163207 中描述的 Webkit 错误一模一样,但据说这个问题已在 iOS 10.3 中修复,而我正在运行 11.3。

捕获touchforcestart 并调用preventDefault 似乎确实阻止了窗口的滚动,但我们在touchstart 中调用它,这似乎“为时已晚”,因为窗口仍在滚动。只有在下次调用 touchstart 时才会阻止滚动。

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

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

touchforcechange?没有它似乎可以工作?【参考方案2】:

我最近遇到了同样的问题。在注册touchmove 事件监听器时,您需要传递 passive: false 。例如

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

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

网络 API

[...] 更新了根文档触摸事件侦听器以使用被动模式提高滚动性能并减少崩溃。

【讨论】:

好东西,谢谢!我们在touchstart 处理程序中添加了touchmove 侦听器,出于某种原因,我似乎也需要取消它(使用preventDefault)以取消touchmove,即使关闭了被动也是如此。 passive: false touchstarttouchmove 事件在我们处理它们后都被取消,它似乎工作得很好。 是否可以在应用此代码后仅在文档内部启用特定 div 中的滚动? @user9576791 如何在点击页面时删除此事件监听器? @user9576791 很好,但现在的问题是您也没有滚动页面。 非常感谢。我一直看到没有被动部分的答案,所以没有用。

以上是关于无法阻止“touchmove”在 iOS 上滚动窗口的主要内容,如果未能解决你的问题,请参考以下文章

js 弹出框 里面元素touchmove时候阻止其他元素滚动,背景遮罩层还无法阻止冒泡,怎么禁用遮罩层touchmove

如何从 IOS Safari 中的 touchmove 事件中检测滚动画布

阻止IOS上的弹性滚动

document.addEventListener("touchmove", preventBehavior, false); - 阻止我使用溢出:滚动; - 变通?

阻止小程序遮罩层下方图层滚动

使用jquery在touchmove上滚动事件