在taphold事件之后jQuery调用click事件

我正在使用Jquery和Jquery Mobile为Android开发PhoneGap应用程序。

我有一个项目列表,需要两个事件绑定到列表中的每个项目。 我需要一个“taphold”活动和一个“点击”活动。 我遇到的问题是当我做“taphold”时,正确的“taphold”事件被解雇了。 但是,一旦我发布,click事件也会被触发。 如何防止点击事件在taphold之后触发?

码:

function LoadMyItems(items) { for(var idx in items) { var itemLine = '
' + '' + items[idx].item.name+ '
'; $('#my_list').append('
  • '+itemLine+'
  • '); $('#my_item_'+items[idx].user_item_id).bind('taphold', {userItem:items[idx]},ShowMyItemInfo); $('#my_item_'+items[idx].user_item_id).bind('click tap', {userItem:items[idx]},FitMyUpgradeItem); console.log('UserItem '+items[idx].user_item_id+' loaded and events bound'); } $('#my_items_loader').hide(); myScroll.refresh(); }

    在下面的建议之后,这就是我最终的结果。 这适用于iScroll对象。

     function LoadMyItems(items) { for(var idx in items) { var itemLine = '
    ' + '' + items[idx].item.name+ '
    '; $('#my_list').append('
  • '+itemLine+'
  • '); (function(index) { var tapTime = 0; var xPos = 0; var yPos = 0; $('#my_item_'+items[index].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { tapTime = new Date().getTime(); xPos = event.pageX; yPos = event.pageY; var timer = setTimeout(function() { var duration = (new Date().getTime() - tapTime); var xDiff = Math.abs(mouseXPos - xPos); var yDiff = Math.abs(mouseYPos - yPos); if(duration >= 700 && (yDiff <= 40 || mouseXPos == 0)) ShowItemInfo(items[index].item); },750); } else { //event.type == 'vmouseup' var duration = (new Date().getTime() - tapTime); var xDiff = Math.abs(event.pageX - xPos); var yDiff = Math.abs(event.pageY - yPos); tapTime = new Date().getTime(); if (duration < 699 && yDiff <= 40) { //this is a tap FitMyUpgradeItem(items[index]); } } }); $('#my_item_'+items[index].user_item_id).bind('touchmove',function(event) { event.preventDefault(); }); })(idx); console.log('UserItem '+items[idx].user_item_id+' loaded and events bound'); } $('#my_items_loader').hide(); myScroll.refresh(); }

    而不是使用taptaphold (我试图使用但遇到同样的问题,似乎是taphold事件的固有问题)你可以使用vmousedown并设置一个标志,然后绑定到vmouseup以确定它是否是一个taptaphold

     var tapTime = 0; $('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { tapTime = new Date().getTime(); } else { //event.type == 'vmouseup' //here you can check how long the `tap` was to determine what do do var duration = (new Date().getTime() - tapTime); if (duration > 3000) { //this is a tap-hold ShowMyItemInfo(items[idx]); } else { //this is a tap FitMyUpgradeItem(items[idx]); } } }); 

    为了使其正常工作,您必须在循环代码周围添加IIFE或更改ShowMyItemInfo(items[idx]); 在不引用改变循环的每次迭代的变量的情况下工作。 一个易于创建IIFE的方法就是使用$.each() 。 否则你的循环看起来像这样:

     for(var idx in items) { (function (idx) { ... })(idx); } 

    IIFE =立即调用函数表达式。 它允许我们对我们传递到IIFE的变量的当前状态进行“快照”。 因此,当我们传入idx (从技术上讲,第二个实例是传入的变量,第一个实例是IIFE中可用的变量,为简单起见,可以将其更改为类似ids_new ),传入的值将被保存当tap事件处理程序触发时。

    更新

    您还可以设置超时以确定taphold而不是使用vmouseup事件:

     //setup a timer and a flag variable var tapTimer, isTapHold = false; $('#my_item_'+items[idx].user_item_id).bind('vmousedown vmouseup', function (event) { if (event.type == 'vmousedown') { //set the timer to run the `taphold` function in three seconds // tapTimer = setTimeout(function () { isTapHold = true; ShowMyItemInfo(items[idx]); }, 3000); } else { //event.type == 'vmouseup' //clear the timeout if it hasn't yet occured clearTimeout(tapTimer); //if the flag is set to false then this is a `tap` event if (!isTapHold) { //this is a tap, not a tap-hold FitMyUpgradeItem(items[idx]); } //reset flag isTapHold = false; } }); 

    这样,在用户按下手指三秒钟后,事件将触发。 然后,如果没有发生三秒钟,则只会触发tap事件处理程序。

    在定义偶数之前,只需将其设置在文档的顶部或任何位置:

     $.event.special.tap.emitTapOnTaphold = false; 

    然后你可以像这样使用它:

     $('#button').on('tap',function(){ console.log('tap!'); }).on('taphold',function(){ console.log('taphold!'); }); 

    就个人而言,我认为这里的答案过于复杂了这个问题。 如果您只是想要一种简单的方法来继续使用taphold事件并忽略释放taphold时触发的click事件,这就是我在自己的项目中解决同样问题的方法:

     // We will use this flag to ignore click events we don't want var skipNextClick = false; //Set up your event handler. You could do these using two handlers or one. I chose one. $('div.element').on('click taphold', function (e) { //set up a quick bool flag that is true if click var isClick = (e.type == 'click'); if (isClick && !skipNextClick) { //run your code for normal click events here... } else if (isClick && skipNextClick) { //this is where skipped click events will end up... //we need to reset our skipNextClick flag here, //this way, our next click will not be ignored skipNextClick = false; } else { //taphold event //to ignore the click event that fires when you release your taphold, //we set the skipNextClick flag to true here. skipNextClick = true; //run your code for taphold events here... } }); 

    使用tap \ vclick和taphold代替 – Tap事件在taphold之后被触发两次。

     $('#my_item_'+items[idx].user_item_id).bind('vclick', ... $('#my_item_'+items[idx].user_item_id).bind('taphold', ... 

    在这个例子中,实际上没有在taphold之后调用click。在这里查看: http : //jsfiddle.net/YL8hj/43/

    编辑:

    jQuery Mobile自动将触摸事件绑定到某些元素。 将iScroll与jQuery Mobile结合使用时,将单独的函数绑定到“touchmove”事件并防止事件冒泡(event.preventDefault())可能是个好主意。 通过这样做,当用户与iScroll元素交互时,jQuery Mobile将无法处理触摸事件。

    另外http://appcropolis.com/blog/jquery-wrapper-for-iscroll/ credit https://stackoverflow.com/a/9408567/643500