消除移动Safari中点击事件的300毫秒延迟

时间:2012-09-02 18:25:10

标签: javascript jquery jquery-mobile safari touch

从点击链接/按钮到事件触发时,我已经读过 mobile Safari has a 300ms delay on click events。延迟的原因是等待用户是否打算双击,但从UX的角度来看,等待300毫秒通常是不可取的。

消除这300ms延迟的

One solution是使用jQuery Mobile“tap”处理。不幸的是,我不熟悉这个框架,如果我需要的是一行或两行以正确方式应用touchend的代码,我不想加载一些大框架。

与许多网站一样,我的网站有很多点击事件,如下所示:

$("button.submitBtn").on('click', function (e) {   
  $.ajaxSubmit({... //ajax form submisssion
});

$("a.ajax").on('click', function (e) {   
  $.ajax({... //ajax page loading
});

$("button.modal").on('click', function (e) {   
      //show/hide modal dialog
});

我想要做的是使用像这样的单个代码片段来消除所有这些点击事件的300毫秒延迟:

$("a, button").on('tap', function (e) {
 $(this).trigger('click');
 e.preventDefault();
});

这是一个坏/好主意吗?

10 个答案:

答案 0 :(得分:60)

现在,如果设置视口,某些移动浏览器会消除300毫秒的点击延迟。您不再需要使用变通办法。

<meta name="viewport" content="width=device-width, user-scalable=no">

目前支持Android版Chrome 适用于Android的Firefox 适用于iOS的Safari

但是在iOS Safari 上,双击是不可分页面上的滚动动画。因此他们无法消除300毫秒的延迟。如果他们无法消除不可编辑页面上的延迟,则他们不太可能在可缩放页面上删除它。

Windows手机也会在不可用的页面上保留300毫秒的延迟,但是他们没有像iOS这样的替代手势,所以他们可以像Chrome一样消除这种延迟。 您可以使用以下方法删除Windows Phone上的延迟:

html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

来源:http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

2015年12月更新

到目前为止,iOS上的WebKit和Safari在单点击激活链接或按钮之前有350毫秒的延迟,以允许人们通过双击放大页面。几个月前Chrome已经通过使用更智能的算法检测到这一点并{{​​3}}改变了这一点。本文提供了一些很好的见解,了解浏览器如何使用触摸手势以及浏览器如何能够比现在更加智能化。

2016年3月更新

在Safari for iOS上,已删除检测第二次点按的350毫秒等待时间,以创建“快速点按”响应。对于声明视口宽度= device-width或user-scalable = no的页面启用此选项。通过使用记录WebKit will follow with a similar approach的CSS touch-action: manipulation(向下滚动到'样式快速点击行为'标题)和here,作者还可以选择快速点击特定元素的行为。

答案 1 :(得分:43)

This plugin -FastClick developed by Financial Times完美适合你!

确保在点击功能之后直接添加event.stopPropagation();和/或event.preventDefault();,否则它可能会像我一样运行两次,即:

$("#buttonId").on('click',function(event){
    event.stopPropagation(); event.preventDefault();
   //do your magic

});

答案 2 :(得分:16)

我知道这已经过时但你不能只测试一下浏览器是否支持“touch”?然后创建一个“touchend”或“click”变量,并将该变量用作绑定到元素的事件?

var clickOrTouch = (('ontouchend' in window)) ? 'touchend' : 'click';
$('#element').on(clickOrTouch, function() {
    // do something
});

以便代码示例检查浏览器是否支持“touchend”事件,如果没有,那么我们使用“click”事件。

(编辑:将“touchend”更改为“ontouchend”)

答案 3 :(得分:12)

我遇到了hugely popular alternative called Hammer.js (Github page),我认为这是最好的方法。

Hammer.js是一个功能更全面的触摸库(有许多滑动命令),而不是Fastclick.js(最热门的答案)。

请注意:在使用Hammer.js或Fastclick.js时,在移动设备上快速滚动往往会真正锁定UI。如果您的网站有新闻源或用户将滚动很多的界面(看起来像大多数网络应用程序),这是一个主要问题。出于这个原因,我目前都没有使用这些插件。

答案 4 :(得分:2)

不知何故,禁用缩放似乎会禁用这个小延迟。有道理,因为不再需要双击。

How can I "disable" zoom on a mobile web page?

但请注意这将产生的可用性影响。它可能对设计为应用程序的网页很有用,但不应用于更通用的“静态”页面恕我直言。我将它用于需要低延迟的宠物项目。

答案 5 :(得分:1)

不幸的是,没有简单的方法可以做到这一点。因此,仅使用touchstarttouchend会让您遇到其他问题,例如有人在点击按钮时开始滚动。我们暂时使用zepto,即使有了这个非常好的框架,也会出现一些问题。其中很多都是closed,但似乎不是简单解决方案的领域。

我们有全球处理链接点击的解决方案:

   $(document.body).
    on('tap', 'a',function (e) {
      var href = this.getAttribute('href');
      if (e.defaultPrevented || !href) { return; }
      e.preventDefault();
      location.href= href;
    }).
    on('click', 'a', function (e) {
      e.preventDefault();
    });

答案 6 :(得分:1)

我搜索了一个简单的方法,没有jquery和没有fastclick库。这对我有用:

var keyboard = document.getElementById("keyboard");
var buttons = keyboard.children;
var isTouch = ("ontouchstart" in window);
for (var i=0;i<buttons.length;i++) {
    if ( isTouch ) {
        buttons[i].addEventListener('touchstart', clickHandler, false);         
    } else {
        buttons[i].addEventListener('click', clickHandler, false);          
    }
}

答案 7 :(得分:0)

只是提供一些额外的信息。

在iOS 10上,我的页面上的<button>无法连续触发。总是有一个滞后。

我试过fastclick / Hammer / tapjs /用touchstart取代点击,都失败了。

更新:原因似乎是按钮太靠近边缘了!把它移到中心附近然后消失了!

答案 8 :(得分:0)

您应该明确声明被动模式

window.addEventListener('touchstart', (e) => {

    alert('fast touch');

}, { passive : true});

答案 9 :(得分:0)

在jQuery中你可以绑定“touchend”事件,在点击之后触发代码(就像键盘中的keydown一样)。在当前的Chrome和Firefox平板电脑版本上进行测试。对于您的触摸屏笔记本电脑和台式设备,请不要忘记“点击”。

jQuery('.yourElements').bind('click touchend',function(event){

    event.stopPropagation();
    event.preventDefault();

	// everything else
});