JavaScript touchend vs点击困境

时间:2014-08-29 16:07:40

标签: javascript jquery ios click touch

我正在开发一些javascript用户界面,并使用很多触摸事件,比如' touchend'用于改善触摸设备的响应。然而,有一些逻辑问题困扰着我......

我看到许多开发人员混在一起' touchend'并点击'在同一事件中。在许多情况下它不会受到伤害,但基本上该功能会在触摸设备上触发两次:

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

有人建议可以检测触摸功能,并适当设置事件,例如:

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

上述问题是它会在支持触控和鼠标的设备上中断。如果用户当前正在双输入设备上使用鼠标,则单击'不会开火,因为只有' touchend'被分配给按钮。

另一种解决方案是检测设备(例如" iOS")并根据以下内容分配事件: Click event called twice on touchend in iPad。 当然,上面链接中的解决方案仅适用于iOS(不是Android或其他设备),看起来更像是" hack"解决一些非常基本的东西。

另一种解决方案是检测鼠标移动,并将其与触摸功能相结合,以确定用户是鼠标还是触摸。问题当然是当用户想要检测它时用户可能没有移动鼠标......

我能想到的最可靠的解决方案是使用一个简单的debounce函数来简单地确保函数只在短时间内触发一次(例如100ms):

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

我错过了什么,或者有人有更好的建议吗?

编辑:我在帖子后发现了这个链接,提出了与上述类似的解决方案: How to bind 'touchstart' and 'click' events but not respond to both?

5 个答案:

答案 0 :(得分:29)

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

我确实找到了一种通过使用stopPropagationpreventDefault两次触摸禁用触发事件的方法,但这很狡猾,因为它可能会干扰其他触摸手势,具体取决于应用它的元素:

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

我实际上是在寻找一个将 touchstart 组合在某些UI元素上的解决方案,但我无法看到如何将其与点击结合起来。上面的解决方案。

答案 1 :(得分:6)

这个问题已得到解答,但可能需要更新。

根据a notice from Google,如果我们在<head>元素中包含以下行,则不会再有300-350ms的延迟。

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

就是这样!点击和触摸事件之间不会有任何区别!

答案 2 :(得分:0)

是禁用双击缩放(因此点击延迟)通常是最佳选择。我们终于有了这样做的好建议soon work on all browsers

如果由于某种原因,您不想这样做。您还可以使用UIEvent.sourceCapabilities.firesTouchEvents明确忽略冗余clickpolyfill for this与您的去抖动代码类似。

答案 3 :(得分:0)

您好,您可以通过以下方式实施。

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...
});

答案 4 :(得分:0)

您的for (NSDictionary *dict in friendorNo) { if ([dict[@"uid"] isEqualToString:testing]) { self.addFriend.hidden = YES; } } 函数会延迟处理每次点击100 ms:

debounce

相反,我创建了一个立即触发的button.on('click touchend', $.debounce(100, function(event) { // this is delayed a minimum of 100 ms })); 函数,但10毫秒内的所有后续调用都将被取消:

cancelDuplicates

用法:

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);
        }
    };
}