我正在开发一个需要在多种设备上运行的移动网站。目前让我头疼的是黑莓手机。
我们需要同时支持键盘点击和触摸事件。
理想情况下,我会使用:
$thing.click(function(){...})
但我们遇到的问题是,一些黑莓设备从触摸到触发点击有一个非常恼人的延迟。
补救方法是使用touchstart:
$thing.bind('touchstart', function(event){...})
但是如何绑定两个事件,但只触发一个事件呢?对于键盘设备,我仍然需要click事件,但当然,如果我使用的是触摸设备,我不想让click事件触发。
一个额外的问题:有没有办法做到这一点,并额外适应那些甚至没有touchstart事件的浏览器?在研究中,看起来黑莓OS5不支持touchstart,因此也需要依赖于该浏览器的点击事件。
附录:
也许一个更全面的问题是:
使用jQuery,是否可能/建议使用相同的绑定同时处理触摸交互和鼠标交互?
理想情况下,答案是肯定的。如果不是,我确实有一些选择:
我们使用WURFL来获取设备信息,这样就可以创建我们自己的设备矩阵。根据设备的不同,我们将使用touchstart或click。
通过JS检测浏览器中的触摸支持(我需要做更多的研究,但这似乎是可行的)。
然而,还有一个问题:支持这两种功能的设备怎么办?我们支持的一些手机(即诺基亚和黑莓)既有触摸屏又有键盘。这让我又回到了最初的问题……有没有一种方法可以同时兼顾两者?
这里有一个简单的方法:
// A very simple fast click implementation
$thing.on('click touchstart', function(e) {
if (!$(document).data('trigger')) $(document).data('trigger', e.type);
if (e.type===$(document).data('trigger')) {
// Do your stuff here
}
});
基本上,您可以将第一个被触发的事件类型保存到附加到根文档的jQuery数据对象中的'trigger'属性中,并且仅当事件类型等于'trigger'中的值时才执行。在触控设备上,事件链可能是“touchstart”后面跟着“click”;然而,“点击”处理程序将不会被执行,因为“点击”与保存在“触发器”(“touchstart”)中的初始事件类型不匹配。
假设,我相信这是一个安全的假设,即你的智能手机不会自发地从触摸设备转变为鼠标设备,否则点击将永远不会注册,因为“触发器”事件类型只保存一次页面加载和“点击”永远不会匹配“touchstart”。
这里有一个你可以玩的代码依赖(试着点击触摸设备上的按钮——应该没有点击延迟):http://codepen.io/thdoan/pen/xVVrOZ
我还实现了一个简单的jQuery插件,通过传递一个选择器字符串来支持jQuery的后代过滤:
// A very simple fast click plugin
// Syntax: .fastClick([selector,] handler)
$.fn.fastClick = function(arg1, arg2) {
var selector, handler;
switch (typeof arg1) {
case 'function':
selector = null;
handler = arg1;
break;
case 'string':
selector = arg1;
if (typeof arg2==='function') handler = arg2;
else return;
break;
default:
return;
}
this.on('click touchstart', selector, function(e) {
if (!$(document).data('trigger')) $(document).data('trigger', e.type);
if (e.type===$(document).data('trigger')) handler.apply(this, arguments);
});
};
Codepen: http://codepen.io/thdoan/pen/GZrBdo/
我不得不做一些类似的事情。下面是一个对我有用的简化版本。如果检测到触摸事件,则删除单击绑定。
$thing.on('touchstart click', function(event){
if (event.type == "touchstart")
$(this).off('click');
//your code here
});
在我的例子中,点击事件被绑定到<a>元素,所以我必须删除点击绑定并重新绑定点击事件,这阻止了<a>元素的默认操作。
$thing.on('touchstart click', function(event){
if (event.type == "touchstart")
$(this).off('click').on('click', function(e){ e.preventDefault(); });
//your code here
});
我相信现在最好的做法是:
$('#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(“点击”)对鼠标和触摸更加兼容。
由此得出的结论是,回到只使用单击事件将是最简单的解决方案。
我还没有做任何跨浏览器测试,看看这是否可行。