JavaScript touchend与点击困境

我正在使用一些JavaScript UI,并使用大量触摸事件(如“touchend”)来改善触摸设备的响应。 但是,有一些逻辑问题,正在窃听我…

我看到许多开发者在同一个事件中混合了“touchend”和“click”。 在许多情况下,它不会受到伤害,但本质上这个function会触发两次触摸设备:

button.on('click touchend', function(event) { // this fires twice on touch devices }); 

有人build议,可以检测触摸function,并适当地设置事件,例如:

 var myEvent = ('ontouchstart' in document.documentElement) ? 'touchend' : 'click'; button.on(myEvent, function(event) { // this fires only once regardless of device }); 

上面的问题是,它会打破支持触摸和鼠标的设备。 如果用户当前正在双input设备上使用鼠标,则“点击”将不会触发,因为只有“touchend”被分配给该button。

另一种解决scheme是检测设备(例如“iOS”),并根据以下事件分配事件: 在iPad中触发两次Click事件 。 当然,上面链接中的解决scheme只适用于iOS(不适用于Android或其他设备),似乎更像是一种“黑客”(hack)来解决相当基本的问题。

另一种解决scheme是检测鼠标移动,并将其与触摸function相结合,以确定用户是在鼠标上还是在触摸上。 问题当然是,用户可能不想移动鼠标,当你想检测到它…

我能想到的最可靠的解决scheme是使用一个简单的去抖function来简单地确保该function仅在短时间间隔内触发一次(例如100ms):

 button.on('click touchend', $.debounce(100, function(event) { // this fires only once on all devices })); 

我错过了什么,还是有没有人有更好的build议?

编辑:我发现这个链接后,我的post,这表明类似的解决scheme,如上所示: 如何绑定“touchstart”和“点击”事件,但不响应两者?

经过一天的研究,我认为最好的解决办法就是坚持点击并使用https://github.com/ftlabs/fastclick来消除触摸延迟。 我不是100%确定这是有效的touchend ,但至less不远。

我想通过使用stopPropagationpreventDefault两次触发触发事件的方法,但是这是有缺陷的,因为它可能会干扰其他触摸手势,具体取决于应用的元素:

 button.on('touchend click', function(event) { event.stopPropagation(); event.preventDefault(); // this fires once on all devices }); 

实际上,我正在寻找一种解决scheme来结合一些UI元素上的touchstart ,但是我看不出上述解决scheme如何与点击相结合。

这个问题已经回答,但可能需要更新。

根据谷歌的通知 ,如果我们在<head>元素中包含下面的行,那么将不会再有300-350毫秒的延迟。

 <meta name="viewport" content="width=device-width"> 

而已! 点击和触摸事件不会有区别!

你好,你可以实现下面的方法。

 function eventHandler(event, selector) { event.stopPropagation(); // Stop event bubbling. event.preventDefault(); // Prevent default behaviour if (event.type === 'touchend') selector.off('click'); // If event type was touch turn off clicks to prevent phantom clicks. } // Implement $('.class').on('touchend click', function(event) { eventHandler(event, $(this)); // Handle the event. // Do somethings... }); 

您的debouncefunction将延迟每100毫秒的点击处理时间:

 button.on('click touchend', $.debounce(100, function(event) { // this is delayed a minimum of 100 ms })); 

相反,我创build了一个cancelDuplicates触发的cancelDuplicates函数,但是在10 ms内的任何后续调用都将被取消:

 function cancelDuplicates(fn, threshhold, scope) { if (typeof threshhold !== 'number') threshhold = 10; var last = 0; return function () { var now = +new Date; if (now >= last + threshhold) { last = now; fn.apply(scope || this, arguments); } }; } 

用法:

 button.on('click touchend', cancelDuplicates(function(event) { // This fires right away, and calls within 10 ms after are cancelled. })); 

是禁用双击缩放(因此点击延迟)通常是最好的select。 我们终于有了很好的build议,可以很快适用于所有的浏览器 。

如果出于某种原因,你不想这样做。 您也可以使用UIEvent.sourceCapabilities.firesTouchEvents明确地忽略多余的click 。 这个polyfill与你的debouncing代码类似。