javascript - 移动设备上的 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';
});
提前致谢!
解决方案
事实证明,这被称为“鬼点击”,出于兼容性原因而存在,实际上是“预期行为”。如果鼠标事件一开始没有绑定到原始元素,我没想到会发生鬼点击,但显然这在某些浏览器中确实发生了。
可以通过在 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();
});
推荐阅读
- javascript - 在不使用时提高 React Native 性能停用组件
- vuejs3 - Vue 会遵循组件或 dom 层次结构来进行键盘事件绑定吗?
- python - 如何计算两个 pandas.Timestamp 系列之间的差异(以纳秒为单位)
- node.js - 如何在 heroku 上设置一个 cookie 进行测试(即使它在 localhost 上运行良好)?
- reactjs - Redux-form 为什么外部输入停止工作?
- swiftui - SwiftUI - HealthKit 中的 DispatchQueue.main.async
- angular - Angular 11 拦截器实现不断显示 Typescript 错误
- sharepoint - Dynamics AX 2012:尝试使用在线共享点作为文档管理目标时出错
- c# - 在 asp.net 核心控制器中获取“请求有效负载”
- javascript - 函数求和 - 为什么在函数上使用 toString