Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/415.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Javascript防止Mobile Safari/iPhone中的触摸事件中的鼠标模拟事件(即点击)_Javascript_Ios_Mobile Safari_Dom Events - Fatal编程技术网

使用Javascript防止Mobile Safari/iPhone中的触摸事件中的鼠标模拟事件(即点击)

使用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过程中还不

在使用交互式DOM元素开发单页Javascript应用程序时,我发现“
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,非常烦人