使用Javascript防止Mobile Safari/iPhone中的触摸事件中的鼠标模拟事件(即点击)
在使用交互式DOM元素开发单页Javascript应用程序时,我发现“使用Javascript防止Mobile Safari/iPhone中的触摸事件中的鼠标模拟事件(即点击),javascript,ios,mobile-safari,dom-events,Javascript,Ios,Mobile Safari,Dom Events,在使用交互式DOM元素开发单页Javascript应用程序时,我发现“mouseover mousemove mousedown mouseup click”序列发生在“touchstart touchsmove touchend”事件序列之后 我还发现,通过在touchstart事件期间执行“事件.preventDefault()”,可以防止“鼠标*-点击”事件发生,但只有在该事件发生时,而不是在touchmove和touchend期间。这是一种奇怪的设计,因为在touchstart过程中还不
mouseover mousemove mousedown mouseup click
”序列发生在“touchstart touchsmove touchend
”事件序列之后
我还发现,通过在touchstart
事件期间执行“事件.preventDefault()
”,可以防止“鼠标*-点击
”事件发生,但只有在该事件发生时,而不是在touchmove
和touchend
期间。这是一种奇怪的设计,因为在touchstart
过程中还不可能知道用户是想拖动或滑动还是只需点击/单击该项目
最后,我在某个地方设置了一个“忽略下一步点击”标志,并将其与时间戳绑定在一起,但这显然不是很干净
有人知道更好的方法吗,还是我们遗漏了什么
请注意,虽然“点击”可以被识别为“
touchstart touchend
”序列(即“否”touchmove
”),但某些事情,例如键盘输入焦点,只能在正确的点击事件中发生。我在制作跨平台HTML5/JS应用程序时遇到类似问题。对我来说,唯一真正的答案是防止触摸事件出现默认,并根据我的逻辑自行管理触摸状态和触发点击、拖动等事件。这听起来比实际情况要可怕得多,但模拟的点击/鼠标事件在大多数移动浏览器上都能完美工作
单击和额外的鼠标序列都是为了方便(和兼容性)。我的经验法则-如果这是为了你的方便,但不方便,最好杀了它
至于输入框,它们只需要touchend事件。我已经消除了点击/鼠标事件,仍然能够让移动浏览器正确响应输入。如果它仍然给您带来问题,您可以修改事件处理程序,使其仅在非输入上抑制事件:
function touchHandler(event) {
var shouldIgnore = event.target != null
&& ( event.target.tagName.toLowerCase() == "input" || event.target.tagName.toLowerCase() == "textarea" );
if(!shouldIgnore) e.preventDefault();
}
我自己提出了一个解决方案,因为我在其他地方没有找到足够的解决方案:
var isTouch = ('ontouchstart' in window);
function kill(type){
window.document.body.addEventListener(type, function(e){
e.preventDefault();
e.stopPropagation();
return false;
}, true);
}
if( isTouch ){
kill('mousedown');
kill('mouseup');
kill('click');
kill('mousemove');
}
检查isTouch
可以让鼠标输入设备正常工作,但会杀死Safari/iOS上的模拟事件。诀窍是在调用addEventListener
时使用useCapture=true
,这样我们就可以在页面中收集所有鼠标事件,而不必在整个web应用程序中破解代码。有关此功能,请参见此处的文档:
编辑:
现在处理这个问题的库更好了,您可以使用类似Fastclick的方法作为替代()。有解决这个问题的方法
还要注意,在使用IE10 preventDefault()时,MSPointerDown事件后不会停止ghost/synthetic/Simulated mouse事件,因此真正的跨浏览器解决方案比较困难。如果您必须支持同时支持鼠标和触摸的设备,另一种解决方案是使用捕获事件监听器,该监听器可停止发生的所有鼠标事件
- 触摸事件后的延迟内
- 在与触摸事件相同的位置
- 在与触摸事件相同的目标元素上
触摸事件的信息(时间、位置或目标元素)可以记录在另一个捕获事件侦听器中。在窗口中包装鼠标代码。matchesMedia函数是我发现的最干净的方法
if (window.matchMedia('(hover: hover), (any-hover: hover), (-moz-touch-enabled: 0)').matches) {
el.addEventListener('mouseover', ev => {
// mouse handler, no simulated hover
}
}
这可以防止模拟悬停,但也可能防止模拟点击
注意:-从版本58开始,Firefox上需要moz touch启用部分。此解决方案允许您侦听PointerEvents
(如果存在),然后是TouchEvents
(如果存在),如果其他两个都不存在,然后是MouseeEvents
。Mobile Safari仍将同时启动touchstart
和mousedown
,但您将只收听touchstart
if (window.PointerEvent) { /* decent browsers */
etouch.addEventListener('pointerdown', (e) => {
console.log('pointerdown');
});
}
else if (window.TouchEvent) { /* mobile Safari */
etouch.addEventListener('touchstart', (e) => {
console.log('touchstart');
});
}
else { /* desktop Safari */
etouch.addEventListener('mousedown', (e) => {
console.log('mousedown');
});
}
当设备支持触摸事件时,您可以尝试在“单击”、“鼠标向下”或“鼠标向下”事件上退出该功能
use.addEventListener("click",function(e){
// EXIT FUNCTION IF DEVICE SUPPORTS TOUCH EVENTS
if ("ontouchstart" in document.documentElement) return false;
// YOURMOUSEONLY CODE HERE
});
只需防止touchend
事件。当您触摸元素时,它将允许浏览器滚动页面,但不会让它发出人造鼠标事件
element.addEventListener('touchend',事件=>{
event.preventDefault();
});
使用'pointerwhatever'
而不是'mousewhather'
似乎在当前浏览器上运行良好(2019)
i、 e.他们发明了一种为所有输入设备提供相同代码的方法。将事件监听器添加到touchstart中,该监听器将属性数据添加到元素中。添加另一个事件侦听器,单击该侦听器可检查所接触的数据。如果存在,请防止默认设置并将其删除。下面是我的实现中的一些JS
var menuLinks = document.querySelectorAll('#my-nav>li>a');
for (var i = 0; i < menuLinks.length; i++) {
var menuLink = menuLinks[i];
menuLink.addEventListener('touchstart', function () {
menuLink.setAttribute('data-touched', '');
});
menuLink.addEventListener('click', function (event) {
if (menuLink.hasAttribute('data-touched')) {
menuLink.removeAttribute('data-touched');
event.preventDefault();
}
});
var menuLinks=document.querySelectorAll('my nav>li>a');
对于(变量i=0;i
我也对iPad Safari touch事件感兴趣,但我不清楚您要解决的具体问题。如果您仍在解决这个问题,或者已经解决了,是否需要详细说明?我希望能够处理某些事件,例如拖放,并且能够处理“点击”事件。我必须处理“点击”事件是正确的“点击”事件(而不是touchstart/touchend),因为某些事情,如键盘输入焦点,只能在点击事件处理程序中激活。这个问题非常烦人,也会影响Android。我同意@RogerBinns,非常烦人