我正在开发一个需要在多种设备上运行的移动网站。目前让我头疼的是黑莓手机。

我们需要同时支持键盘点击和触摸事件。

理想情况下,我会使用:

$thing.click(function(){...})

但我们遇到的问题是,一些黑莓设备从触摸到触发点击有一个非常恼人的延迟。

补救方法是使用touchstart:

$thing.bind('touchstart', function(event){...})

但是如何绑定两个事件,但只触发一个事件呢?对于键盘设备,我仍然需要click事件,但当然,如果我使用的是触摸设备,我不想让click事件触发。

一个额外的问题:有没有办法做到这一点,并额外适应那些甚至没有touchstart事件的浏览器?在研究中,看起来黑莓OS5不支持touchstart,因此也需要依赖于该浏览器的点击事件。

附录:

也许一个更全面的问题是:

使用jQuery,是否可能/建议使用相同的绑定同时处理触摸交互和鼠标交互?

理想情况下,答案是肯定的。如果不是,我确实有一些选择:

我们使用WURFL来获取设备信息,这样就可以创建我们自己的设备矩阵。根据设备的不同,我们将使用touchstart或click。 通过JS检测浏览器中的触摸支持(我需要做更多的研究,但这似乎是可行的)。

然而,还有一个问题:支持这两种功能的设备怎么办?我们支持的一些手机(即诺基亚和黑莓)既有触摸屏又有键盘。这让我又回到了最初的问题……有没有一种方法可以同时兼顾两者?


当前回答

如果你正在使用jQuery,下面的工作对我来说很好:

var callback; // Initialize this to the function which needs to be called

$(target).on("click touchstart", selector, (function (func){
    var timer = 0;
    return function(e){
        if ($.now() - timer < 500) return false;
        timer = $.now();
        func(e);
    }
})(callback));

其他解决方案也很好,但我在一个循环中绑定多个事件,需要自调用函数来创建适当的闭包。此外,我不想禁用绑定,因为我希望它可以在下次单击/触摸启动时调用。

可能会帮助到有类似情况的人!

其他回答

尝试使用虚拟鼠标(vmouse)绑定从jQuery移动。 这是针对你的案例的虚拟事件:

$thing.on('vclick', function(event){ ... });

http://api.jquerymobile.com/vclick/

浏览器支持列表:http://jquerymobile.com/browser-support/1.4/

我相信现在最好的做法是:

$('#object').on('touchend mouseup', function () { });

触端

触摸点从触摸表面移除时触发touchend事件。

touchend事件不会触发任何鼠标事件。


mouseup

当鼠标指针在元素上时,mouseup事件被发送给元素,并且鼠标按钮被释放。任何HTML元素都可以接收这个事件。

mouseup事件不会触发任何触摸事件。

例子

$('#click').on('mouseup', function () { alert('Event detection'); }); $('#touch').on('touchend', function () { alert('Event detection '); }); <script src=“https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js”></script> <h1 id=“点击”>点击我</h1> <h1 id=“触摸”>触摸我</h1>


编辑(2017)

截至2017年,以Chrome为首的浏览器正在采取措施,通过消除点击请求上的点击事件产生的延迟,使点击事件.on(“点击”)对鼠标和触摸更加兼容。

由此得出的结论是,回到只使用单击事件将是最简单的解决方案。

我还没有做任何跨浏览器测试,看看这是否可行。

另一种更好维护的实现。然而,这种技术也会做事件。stopPropagation()。在100毫秒内,没有捕捉到任何其他元素的单击。

var clickObject = {
    flag: false,
    isAlreadyClicked: function () {
        var wasClicked = clickObject.flag;
        clickObject.flag = true;
        setTimeout(function () { clickObject.flag = false; }, 100);
        return wasClicked;
    }
};

$("#myButton").bind("click touchstart", function (event) {
   if (!clickObject.isAlreadyClicked()) {
      ...
   }
}

在试图解决这个问题时,有很多事情需要考虑。大多数解决方案要么中断滚动,要么不能正确处理幽灵点击事件。

完整的解决方案请参见https://developers.google.com/mobile/articles/fast_buttons

注意:你不能在每个元素的基础上处理鬼点击事件。延迟的点击是由屏幕位置触发的,所以如果你的触摸事件以某种方式修改了页面,点击事件将被发送到页面的新版本。

这是修复,我“创建”,它拿出GhostClick和实现FastClick。你自己试试,让我们知道它是否对你有效。

$(document).on('touchstart click', '.myBtn', function(event){
        if(event.handled === false) return
        event.stopPropagation();
        event.preventDefault();
        event.handled = true;

        // Do your magic here

});