我正在开发一些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?
答案 0 :(得分:29)
经过一天的研究,我认为最好的解决方案是坚持点击并使用https://github.com/ftlabs/fastclick来消除触摸延迟。我并非100%确定这与 touchend 一样有效,但至少距离不远。
我确实找到了一种通过使用stopPropagation
和preventDefault
两次触摸禁用触发事件的方法,但这很狡猾,因为它可能会干扰其他触摸手势,具体取决于应用它的元素:
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
明确忽略冗余click
。 polyfill 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);
}
};
}