首页 > 解决方案 > 移动设备上的 Google Chrome 会在文件输入时触发额外的不需要的 MouseEvent

问题描述

我在移动设备上遇到了与 Google Chrome (78) 相关的一些事件相关问题。我有一个设置,其中单击按钮时会附加文件输入(包括标签)。文件输入将完全替换按钮,并将附加到与按钮最初所在的位置完全相同的位置。

在大多数浏览器上,这工作正常。然而,谷歌浏览器的移动版本似乎会在首次触摸按钮后触发延迟点击事件,从而导致点击激活文件上传对话框。即使在初始触摸期间文件输入甚至不存在,也会在文件输入上触发此单击。

无法停止按钮单击时的传播,因为我正在侦听 TouchEvent,但附加事件是 MouseEvent。我宁愿不听 MouseEvent 只是为了 stopPropagation 以防止任何跨浏览器问题。PreventDefault 也不是一个选项,因为按钮位于滑块中,这会破坏滑块的功能。

另一种选择是隐藏文件输入,直到事件循环通过(setTimeout 为 0),这基本上解决了这个问题,但我希望有一个更优雅的解决方案。你们中的任何人都对这些问题有任何潜在的解决方法吗?

我已经设置了一个 CodePen,其中包含一个展示问题的最小代码示例:https ://codepen.io/frankderouge/pen/wvvRPRV

基本设置是文件输入最初是隐藏的,然后在单击按钮时显示。

//This listener is added to the 'button'
document.querySelector('.toggle_off').addEventListener('touchstart', (e) => {

  //This won't do anything since we're handling a touch event, not a click event. 
  e.stopPropagation();  

  //This fixes the dialog open but would break sliding functionality
  //e.preventDefault();

  //Hide the button
  e.target.style.display = 'none';

  //Then show the file input, on which the additional event will be triggered
  document.querySelector('.toggle_on').style.display = 'block';
});

提前致谢!

标签: javascriptgoogle-chromedom-events

解决方案


事实证明,这被称为“鬼点击”,出于兼容性原因而存在,实际上是“预期行为”。如果鼠标事件一开始没有绑定到原始元素,我没想到会发生鬼点击,但显然这在某些浏览器中确实发生了。

可以通过在 TouchEvent 上调用 preventDefaulton 来防止重影点击,在最初的帖子中我说:

PreventDefault 也不是一个选项,因为按钮位于滑块中,这会破坏滑块的功能。

但是我最近了解到,调用 preventDefault 的触摸的哪个“部分”并不重要,因为在所有触摸事件之后总是会触发幽灵点击。因此,如果在 touchend 而不是 touchstart 或 touchmove 上调用 preventDefault,则不会发生滚动被阻止的问题。

document.querySelector('.element').addEventListener('touchstart', (e) => {
  //Process the touch start event
});

document.querySelector('.element').addEventListener('touchend', (e) => {
  //Prevent default on the touchend, preventing the ghost click from happening
  //But still allowing the users to zoom and scroll
  e.preventDefault();
});

推荐阅读