如何绑定“ touchstart”和“ click”事件,但不响应两者?


198

我正在一个必须在各种设备上工作的移动网站上。目前让我头疼的是黑莓。

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

理想情况下,我只会使用:

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

但我们遇到的问题是,这些黑莓设备中的某些设备从触摸到触发点击之间都存在非常令人讨厌的延迟。

补救措施是改为使用touchstart:

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

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

一个额外的问题:是否仍然可以这样做,并且还可以容纳甚至没有touchstart事件的浏览器?在进行研究时,BlackBerry OS5似乎不支持touchstart,因此还需要依赖于该浏览器的单击事件。

附录:

也许更全面的问题是:

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

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

1)我们使用WURFL获取设备信息,因此可以创建我们自己的设备矩阵。根据设备,我们将使用touchstart或click。

2)通过JS检测浏览器中的触摸支持(我需要对此进行更多研究,但这似乎是可行的)。

但是,这仍然存在一个问题:同时支持两者的设备又如何呢?我们支持的某些手机(即诺基亚和BlackBerries)同时具有触摸屏键盘。因此,这使我全神贯注于最初的问题...是否有办法以某种方式同时允许这两者?


2
您最好将其绑定到touchstart和touchend,并在触摸逻辑旁边编写自己的单击逻辑。内置的点击回调功能,无需任何触摸。
Justin808

我不确定我会跟随,贾斯汀。我是否仍会同时具有touchstart和click事件?
DA。

@DA-不,您根本不会绑定到.click()回调。我将尝试用一些sudo代码编写答案。我没有方便的触摸设备来编写真实的代码:)
Justin808

嗯,但要澄清一下,我仍然需要单击事件,因为会有人使用非触摸设备访问此网站。
DA。

2
使用.bind('touchstart mouseup')将解决该问题(基于以下评论之一)
oriadam

Answers:


135

更新:检查jQuery 指针事件Polyfill项目,该项目使您可以绑定到“指针”事件,而无需在鼠标和触摸之间进行选择。


绑定到两者,但创建一个标志,以便该函数每100ms左右仅触发一次。

var flag = false;
$thing.bind('touchstart click', function(){
  if (!flag) {
    flag = true;
    setTimeout(function(){ flag = false; }, 100);
    // do something
  }

  return false
});

7
嗯...感觉很hacky,但是可以用。问题是,在其中一些设备上,这是一个明显的滞后……可能接近一秒钟……这对于使用更快的设备的其他人来说很烦人。
DA。

15
而不是使用clickchange来mousedown...可能长的延迟是a的不同mousedown以及mouseupa click的确定方式。
Mottie 2011年

7
这是我的解决方案。谢谢!我要做的是touchend通过应用标记一个项目touched。在点击事件被调用之前触发。然后,我添加一个click事件,该事件首先检查该类的存在。如果存在,则假定触发了触摸事件,并且除了删除类名以将其“重置”用于下一次交互外,我们不执行其他任何单击操作。如果不存在该类,则我们假设他们已使用键盘单击该项目并从那里触发功能。
DA。

7
您应该知道,大多数电话浏览器的click事件都会延迟300毫秒,因此您应该将延迟增加到至少300 毫秒有关300毫秒延迟问题,请参阅本文。基本上,这是为了启用“双击缩放”功能,这在iPhone初期是非常重要的功能,当时大多数网站都旨在在大型桌面屏幕上查看。
畏惧

12
目前,这个问题已被观看了近10万次。这似乎是一个非常普通的用例/问题。但是,这个答案以及与此有关的其他问题以及类似的问题似乎都不可靠。Google解决方案虽然比大多数解决方案都经过了透彻的思考,但似乎仅仅是一种更强大的工具。对于像单击处理程序这样简单的事情,似乎解决方案应该很简单。没有人找到针对此问题的非黑客解决方案吗?
jinglesthula

73

这是我“创建”的修复程序,它删除了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

});

2
helgatheviking:jsbin.com/ijizat/25 在JavaScript中,有一个名为TouchClick的函数,其中包含上述内容。
马特·帕金斯

5
对于这个问题,我非常喜欢这种方法,因为它是a)不测试设备功能,b)不使用setTimeout。以我的经验,使用setTimeout的此类问题的解决方案在大多数情况下可能有效,但是事件的时间安排是相当随意的,并且是特定于设备的。
itsmequinn 2013年

7
这是行不通的,因为通过在匿名函数中传递“事件”,它会成为该函数内的本地对象,因此每次触发事件时event.handled都相等undefined。这是一个解决方案:通过使用在目标元素本身中设置“ handled”标志jQuery.data()
thdoan's

3
你必须event.stopPropagation();event.preventDefault();从我的理解(和测试)的情况下只能用这种触发一次。那为什么还要检查if(event.handled !== true)呢?对我来说没有必要,还是我想念什么?
nbar

2
event.handled应该检查该值true吗?据我所知从来没有false。它以开头undefined,然后您要告诉它是否已设置为true
ACJ

49

您可以尝试这样的事情:

var clickEventType=((document.ontouchstart!==null)?'click':'touchstart');
$("#mylink").bind(clickEventType, myClickHandler);

5
我认为问题在于测试设备功能而不是用户正在做什么,对吗?挑战在于,我们需要支持还具有键盘的触摸设备(以便它们可以同时使用)
DA。

8
这不是一个好主意-使用鼠标和触摸屏的用户(使用触摸屏的笔记本电脑将变得非常普遍)会破坏事件。
Kristian J.

1
与此相关的优秀文章:hacks.mozilla.org/2013/04/…–
Luke Melia

如果使用Windows 8,它将始终连接“ touchstart”事件,因为“ ontouchstart”将为此操作系统返回“ true”。因此,除非您的代码仅在真正的触摸屏设备上运行,否则可能不是最佳答案,但是如果是这样,您根本不需要进行检查。
尼尔·梦露

在带触摸屏的笔记本电脑上,用户将无法使用此Chrome代码(至少Chrome 46)来单击任何内容。IE 11似乎可以工作。
大卫·谢里

42

通常这也可以:

$('#buttonId').on('touchstart click', function(e){
    e.stopPropagation(); e.preventDefault();
    //your code here

});

8
@Jonathan错误,如果您正在使用较新的jQuery版本。1.7版不推荐使用Live。
Mike Barwick

我还尝试了e.stopPropagation()(在其他地方读过-不是我的主意);e.preventDefault(); 几乎可以(对我来说)有效,但后来我发现实际上它可以按预期的方式工作20次,但不能达到预期的1次,因此它不是防弹的。请看这里:stackoverflow.com/questions/25671053/…感谢您对此问题的评论!
Garavani 2014年

@MikeBarwick您能解释一下您的评论或提供解释它的链接吗?先感谢您。
Billal Begueradj 2016年

22

只需return false;on("click touchstart")事件函数的末尾添加即可解决此问题。

$(this).on("click touchstart", function() {
  // Do things
  return false;
});

来自.on()上的jQuery文档

false从事件处理程序返回将自动调用event.stopPropagation()event.preventDefault()false也可以为处理程序传递一个值,作为的简写形式function(){ return false; }


2
与这两个设备的伟大工程,火灾只有一次-这似乎是最干净的至少哈克解决方案,我
亚当库珀

最适合我,实际上可以理解为什么。
Amir5000 '16

有任何不利之处吗?为什么这种简单的解决方案没有广为人知?
ESR

10

我不得不做类似的事情。这是对我有用的简化版本。如果检测到触摸事件,请删除单击绑定。

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click');

  //your code here
});

在我的情况下,click事件绑定到一个<a>元素,因此我必须删除click绑定并重新绑定一个click事件,这阻止了该<a>元素的默认操作。

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click').on('click', function(e){ e.preventDefault(); });

  //your code here
});

我希望它能按原样工作,但事实并非如此。$(this)并不指向您认为的内容。
Dave Lowerre 2014年

8

我通过以下方式成功。

十分简单...

$(this).on('touchstart click', function(e){
  e.preventDefault();
  //do your stuff here
});

4
不会在同时注册点击和触摸开始的设备上触发两次?
DA。

8
对不起,我知道你的意思。是的,您说对了,触摸也会生成touchstart事件和click事件。这称为“幽灵点击”。Google为此实现了一个解决方案。可能不直接,但效果很好。链接在这里。code.google.com/mobile/articles/fast_buttons.html#ghost
Hasanavi 2012年

2
可能是微不足道的,但是您efunction()
ProblemsOfSumit

@Hasanavi,这是一个不错的解决方法,但是我使用.on
Neil

1
谢谢@尼尔。是的,最好使用.on,因为将来的版本中可能会删除它。我将示例从绑定更改为启用。
Hasanavi

5

我相信最佳做法是现在使用:

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

触摸端

当从触摸表面上移除触摸点时,将触发touchend事件。

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


鼠标向上

当鼠标指针悬停在元素上,并且释放鼠标按钮时,mouseup事件将发送到该元素。任何HTML元素都可以接收此事件。

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

$('#click').on('mouseup', function () { alert('Event detected'); });
$('#touch').on('touchend', function () { alert('Event detected'); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="click">Click me</h1>
<h1 id="touch">Touch me</h1>


编辑(2017)

截至2017年,浏览器从Chrome开始,并逐步实现点击事件 .on("click")通过消除点击请求上的点击事件产生的延迟与鼠标和触摸更加兼容。

由此得出的结论是,退回到仅使用click事件将是前进的最简单的解决方案。

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


这对我来说似乎很有前途,所以我把它弄乱了,但最终我发现mouseup了不可预测的结果,尤其是在使用触控板而不是传统鼠标时。
skybondsor

4

通常,您不想混合使用默认的触摸和非触摸(单击)API。一旦进入触摸世界,仅处理与触摸相关的功能就变得更加容易。下面是一些伪代码,可以执行您想要的操作。

如果您在touchmove事件中进行连接并跟踪位置,则可以在doTouchLogic函数中添加更多项以检测手势和其他内容。

var touchStartTime;
var touchStartLocation;
var touchEndTime;
var touchEndLocation;

$thing.bind('touchstart'), function() {
     var d = new Date();
     touchStartTime = d.getTime();
     touchStartLocation = mouse.location(x,y);
});

$thing.bind('touchend'), function() {
     var d = new Date();
     touchEndTime= d.getTime();
     touchEndLocation= mouse.location(x,y);
     doTouchLogic();
});

function doTouchLogic() {
     var distance = touchEndLocation - touchStartLocation;
     var duration = touchEndTime - touchStartTime;

     if (duration <= 100ms && distance <= 10px) {
          // Person tapped their finger (do click/tap stuff here)
     }
     if (duration > 100ms && distance <= 10px) {
          // Person pressed their finger (not a quick tap)
     }
     if (duration <= 100ms && distance > 10px) {
          // Person flicked their finger
     }
     if (duration > 100ms && distance > 10px) {
          // Person dragged their finger
     }
}

我想这就是问题的症结所在:尝试用一个代码库支持两个模型甚至有意义吗?我将在更多情况下更新我的问题。
DA。

1
我同意,“通常,您不想混合使用默认触摸和非触摸”。问题是他们一直在用键盘制造触摸设备,这对于我们开发人员来说是一个头疼的问题。
DA。

我同意,在最终js决策接触或不接触的开始之初,这样做会容易得多。多么简单的世界!但是,那些该死的设备的点击和触摸明智呢?所有因这些头痛而引起的头痛值得吗?我问自己这是未来吗?
Garavani 2014年

我不喜欢具有多个函数定义的想法。我公司目前正在从事一个项目,在该项目中,iPad没有作为移动设备进行特殊处理,您仍然需要touchend事件。但是touchend在普通的桌面版本上不起作用。因此,对于这种情况,@ mottie的解决方案是绝对好的。
皮特2015年


3

好吧...所有这些都超级复杂。

如果您拥有现代化的产品,那就很容易了。

ev = Modernizr.touch ? 'touchstart' : 'click';

$('#menu').on(ev, '[href="#open-menu"]', function(){
  //winning
});

2
能解释一下吗?我相信它会检查设备是否支持触摸,如果不支持,则使用click。渔获量是(或至少在我写问题时,)某些设备支持这两种设备。在这些设备上,我仍然需要处理这两个事件,因为触发可能来自触摸或单击。
DA。

2
我建议多一点解释。
亚伦·霍尔

2

另一个实现更好维护的实现。但是,此技术也会做event.stopPropagation()。单击不会被单击持续100ms的任何其他元素捕获。

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()) {
      ...
   }
}

2

仅出于文档目的,这是我想到的最快/响应最快的台式机/移动解决方案点击操作:

我替换了jQuery的 on修改后功能功能,每当浏览器支持触摸事件时,我的所有单击事件都用touchstart替换了。

$.fn.extend({ _on: (function(){ return $.fn.on; })() });
$.fn.extend({
    on: (function(){
        var isTouchSupported = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
        return function( types, selector, data, fn, one ) {
            if (typeof types == 'string' && isTouchSupported && !(types.match(/touch/gi))) types = types.replace(/click/gi, 'touchstart');
            return this._on( types, selector, data, fn);
        };
    }()),
});

用法将与以前完全相同,例如:

$('#my-button').on('click', function(){ /* ... */ });

但是它会在可用时使用touchstart,在不可用时单击。无需任何延迟:D


1
与此相关的是需要同时支持触摸和键盘的设备,以确保同时容纳两种交互。
DA。

良好的观察@DA。我添加了一项检查,仅在您未结合使用任何触摸事件时才替换click事件。Stil并不是每个项目的解决方案,但是我敢肯定,它很适合许多项目。
Gerson Goulart

2

我只是想出一个想法来记住是否ontouchstart曾经被触发过。在这种情况下,我们在支持它的设备上并且想要忽略该onclick事件。由于ontouchstart应该始终在之前 触发onclick,因此我在使用:

<script> touchAvailable = false; </script>
<button ontouchstart="touchAvailable=true; myFunction();" onclick="if(!touchAvailable) myFunction();">Button</button>


1
由于用户可能在同一页访问期间使用触摸和鼠标,因此此代码段的问题是它只注册一次touchAvailable标志,而不是针对每个事件注册。来自stackoverflow.com/a/26145343/328272的jQuery插件与您的代码相同,但是可以告知鼠标事件是事件触发还是触摸触发。不仅如此。单击时,也可能在鼠标离开时(可能在鼠标进入后几秒(或几分钟)触发)(弹出菜单的理想选择,当鼠标悬停在鼠标上时,展开菜单应该扩展,或者在使用触摸时单击)。
lmeurs 2014年

2

您可以这样尝试:

var clickEvent = (('ontouchstart' in document.documentElement)?'touchstart':'click');
$("#mylink").on(clickEvent, myClickHandler);

支持触摸和鼠标的设备怎么样
Walle Cyril

2

就我而言,这很完美:

jQuery(document).on('mouseup keydown touchend', function (event) {
var eventType = event.type;
if (eventType == 'touchend') {
    jQuery(this).off('mouseup');
}
});

主要问题是,当我尝试在触摸设备上同时单击clickup的mouseup触发了click和touchend时,如果我使用click off,则某些功能根本无法在移动设备上使用。点击的问题在于,这是一个全局事件,会触发事件的其余部分,包括touchend。


1

这对我来说很有效,移动设备既可以听又可以听,所以请避免同时听,这是触摸事件。桌面只听鼠标。

 $btnUp.bind('touchstart mousedown',function(e){
     e.preventDefault();

     if (e.type === 'touchstart') {
         return;
     }

     var val = _step( _options.arrowStep );
               _evt('Button', [val, true]);
  });

1

对我来说,Mottie给出的最佳答案是我正在尝试使他的代码更可重用,所以这是我的贡献:

bindBtn ("#loginbutton",loginAction);

function bindBtn(element,action){

var flag = false;
$(element).bind('touchstart click', function(e) {
    e.preventDefault();
    if (!flag) {
        flag = true;
        setTimeout(function() {
            flag = false;
        }, 100);
        // do something
        action();
    }
    return false;
});

0

我还在Android / iPad Web应用程序上工作,似乎只要使用“ touchmove”就足以“移动组件”(无需touchstart)。通过禁用touchstart,可以使用.click();。来自jQuery。它之所以有效,是因为touchstart并没有使它过载。

最后,您可以将.live(“ touchstart”,function(e){e.stopPropagation();})装箱。要求touchstart事件停止传播,客厅单击click()触发。

它为我工作。


您将如何禁用touchstart
punkrockbuddyholly 2012年

我相信您“可以”做类似的事情:jQuery(“#my_element”)。on('touchstart',function(e){e.preventDefault()});
nembleton,2012年

0

解决此问题时,需要考虑许多事项。大多数解决方案要么中断滚动,要么无法正确处理幻像单击事件。

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

注意:您不能按每个元素处理幻影点击事件。屏幕位置会触发延迟的单击,因此,如果您的触摸事件以某种方式修改了页面,则该单击事件将发送到该页面的新版本。


0

分配给事件'touchstart mousedown''touchend mouseup'避免使用的不良副作用可能是有效的click


0

利用单击将始终跟随触摸事件这一事实,这是我要做的,摆脱了“重击”,而不必使用超时或全局标志。

$('#buttonId').on('touchstart click', function(event){
    if ($(this).data("already")) {
        $(this).data("already", false);
        return false;
    } else if (event.type == "touchstart") {
        $(this).data("already", true);
    }
    //your code here
});

基本上,每当ontouchstart元素上触发事件时,都会在单击时标记一个集合,然后将其删除(并忽略)。


0

为什么不使用jQuery Event API?

http://learn.jquery.com/events/event-extensions/

我成功地使用了这个简单的事件。它干净,可命名空间且足够灵活以进行改进。

var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var eventType = isMobile ? "touchstart" : "click";

jQuery.event.special.touchclick = {
  bindType: eventType,
  delegateType: eventType
};

1
建议对用户代理嗅探使用功能检测。
jinglesthula

渔获物是同时支持触摸和点击的设备。
DA。

0

如果您使用的是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));

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

可能会帮助处于类似情况的人!


0

对于简单功能,只需识别触摸或单击“我使用以下代码”:

var element = $("#element");

element.click(function(e)
{
  if(e.target.ontouchstart !== undefined)
  {
    console.log( "touch" );
    return;
  }
  console.log( "no touch" );
});

如果定义了touchstart事件,它将返回“ touch”,否则将返回“ no touch”。就像我说的那样,这是单击/点击事件的一种简单方法。


0

我正在尝试此操作,到目前为止它仍然有效(但我仅在Android / Phonegap上使用,请注意

  function filterEvent( ob, ev ) {
      if (ev.type == "touchstart") {
          ob.off('click').on('click', function(e){ e.preventDefault(); });
      }
  }
  $('#keypad').on('touchstart click', '.number, .dot', function(event) {
      filterEvent( $('#keypad'), event );
      console.log( event.type );  // debugging only
           ... finish handling touch events...
  }

我不喜欢每次触摸都重新绑定处理程序这一事实,但是所有被认为是触摸的事情并不经常发生(在计算机时间内!)。

我有大量的处理程序,例如用于“ #keypad”的处理程序,因此拥有一个简单的函数即可让我在无需太多代码的情况下处理问题,这就是为什么我采用这种方式。



0

编辑:我以前的答案(基于该线程中的答案)不是我的方法。我希望有一个子菜单在鼠标输入或触摸单击时展开,而在鼠标离开或另一触摸单击时折叠。由于通常在触摸事件之后触发鼠标事件,因此编写同时支持触摸屏和鼠标输入的事件侦听器有点棘手。

jQuery插件:触摸或鼠标

我最后写了一个名为“ Touch Or Mouse ”(最小897字节)的jQuery插件,它可以检测事件是由触摸屏还是鼠标调用的(无需测试触摸支持!)。这使得触摸屏和鼠标的支持,同时事件完全分开。

这样,OP可以使用touchstarttouchend快速响应触摸点击以及由鼠标click调用的点击。

示范

第一个必须做出即。body元素跟踪触摸事件:

$(document.body).touchOrMouse('init');

鼠标事件以默认方式绑定到元素,通过调用,$body.touchOrMouse('get', e)我们可以找出事件是由触摸屏还是鼠标调用的。

$('.link').click(function(e) {
  var touchOrMouse = $(document.body).touchOrMouse('get', e);

  if (touchOrMouse === 'touch') {
    // Handle touch click.
  }
  else if (touchOrMouse === 'mouse') {
    // Handle mouse click.
  }
}

http://jsfiddle.net/lmeurs/uo4069nh上查看工作中的插件

说明

  1. 该插件需要在ie上调用。主体元素来跟踪touchstarttouchend事件,因此touchend不必在触发元素(即链接或按钮)上触发事件。在这两个touch事件之间,此插件认为任何要通过touch调用的鼠标事件。
  2. 只有在之后touchend的鼠标事件ghostEventDelay(默认情况下为1000ms)内触发鼠标事件时,才会触发鼠标事件touchend,此插件认为鼠标事件是通过touch调用的。
  3. 使用触摸屏单击某个元素时,该元素会获得:active状态。mouseleave仅在元素通过ie失去此状态后才触发该事件。单击另一个元素。由于mouseenter事件触发后可能需要几秒钟(或几分钟!),因此此插件会跟踪元素的上一个mouseenter事件:如果上一个mouseenter事件是通过touch调用的,则以下mouseleave事件也被认为是touch调用的。

0

这是一种简单的方法:

// 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”。但是,“ click”处理程序将不会执行,因为“ click”与“ trigger”(“ touchstart”)中保存的初始事件类型不匹配。

我相信这是一个安全的假设,那就是您的智能手机不会自发地从触摸设备更改为鼠标设备,否则水龙头将永远不会注册,因为“触发”事件类型每次仅保存一次页面加载和“点击”将永远不会与“ touchstart”匹配。

这是一个可以使用的Codepen(尝试在触摸设备上点击按钮-应该没有单击延迟):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/


为什么在文档上使用数据属性而不是仅使用变量?
拉斐尔·史威克

@RaphaelSchweikert可能只是出于习惯。没有正确或错误的方法,但是我喜欢用来$.data()存储可以被多个函数访问但不属于全局范围的数据。一个优点是,由于我将其存储在一个元素中,因此自然可以为我提供更多上下文。
thdoan '16

0

我发现最好的方法是编写touch事件,并以编程方式使该事件调用正常的click事件。这样,您可以拥有所有常规的单击事件,然后只需为所有触摸事件添加一个事件处理程序。对于每个要使其可触摸的节点,只需向其添加“ touchable”类以调用触摸处理程序。使用Jquery,它的工作原理与逻辑类似,以确保它是真实的触摸事件,而不是误报。

$("body").on("touchstart", ".touchable", function() { //make touchable  items fire like a click event
var d1 = new Date();
var n1 = d1.getTime();
setTimeout(function() {
    $(".touchable").on("touchend", function(event) {
        var d2 = new Date();
        var n2 = d2.getTime();
        if (n2 - n1 <= 300) {
            $(event.target).trigger("click"); //dont do the action here just call real click handler
        }
    });
}, 50)}).on("click", "#myelement", function() {
//all the behavior i originally wanted
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.