2012-05-29 151 views
11

我用jquery mobile'tap'事件测试过,发现它被触发了两次,每次触发。代码如下的html页面:jQuery手机触发事件触发两次

<!DOCTYPE html> 
<html> 
<head> 
    <title>Demo</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">  
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>  
    <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.js"></script>  
    <style> 
     #box{ 
      background-color:red; 
      width:200px; 
      height:200px; 
     } 
    </style> 
</head> 
<body> 
    <div id="box"> 
     tapped me 
    </div> 
    <script type="text/javascript"> 
     $(document).ready(function() { 
      $('#box').bind('tap',function(event) { 
       alert('why'); 
      }); 
     }); 
    </script> 
</body> 
</html> 

更讽刺的是,当我测试过这个的jsfiddle,它只触发事件为一次

这是链接。 http://jsfiddle.net/mochatony/tzQ6D/6/

经过进一步测试后,我发现这个bug已经消失,将javascript放在标题部分。

<!DOCTYPE html> 
<html> 
<head> 
    <title>Demo</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">  
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> 
    </script> 
    <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.js"> 
    </script> 
    <style type="text/css"> 
     #box{ background-color:red; width:200px; height:200px; } 
    </style> 
    <script type="text/javascript"> 
     $(document).ready(function() { 
      $('#box').bind('tap', function(event) { 
       alert('halo'); 
      }); 
     }); 
    </script>   
</head> 
<body> 
    <div id="box"> 
     tapped me 
    </div> 
</body> 
</html> 

我无法解释为什么在body和header部分的放置使这个不同。

回答

5

jQuery Mobile page

重要提示:使用的$(document).bind( 'pageinit'),而不是$(文件)。就绪()
你的jQuery学习的第一件事就是调用 $(document).ready()函数中的代码,以便在加载DOM时加载 。但是,在jQuery Mobile中,Ajax用于在导航时将每个页面的 内容加载到DOM中,DOM准备好的 处理程序仅对第一页执行。要在加载和创建新页面时执行代码,可以绑定到pageinit事件。 此事件在本页底部详细解释。

所以跳过$(document).ready()。更多信息here

+2

感谢您的答复。用pageinit做了一次测试,pageinit事件也被触发了两次。我测试了Firefox和Chrome。对我来说似乎很奇怪。 – TonyTakeshi

9

您正在经历鬼点击问题......这是一个已知的“错误”,很难解决。

更多的相关信息有:

http://forum.jquery.com/topic/tap-fires-twice-with-live-tap https://developers.google.com/mobile/articles/fast_buttons http://philosopherdeveloper.wordpress.com/2011/11/01/ghost-clicks-in-jquery-mobile/

在第一个链接,你会发现一个黑客工具,做的伎俩。据我所知,有没有简单的解决方案:(

顺便说一句:即使它不会解决你的问题,@Sagiv是正确的.JQuery手机经常使用ajax更改页面,因此不会触发文档。 ready事件。

+1

感谢您的回复。如果将代码放在标题部分,我发现问题不复存在。不知道为什么。 – TonyTakeshi

15

我忘了,我看到了这一点,但问题是,jQuery Mobile的是为了模拟结合触摸和鼠标事件“龙头”,并在某些情况下,Android将火两者。

这个技巧对我来说就是在你的事件处理函数中调用preventDefault,这样可以避免重复事件发生。

至于为什么有时只有这种情况,我知道移动浏览器将尝试只触发鼠标版本的事件,如果有人没有听到触摸版本。检测或jQuery的委托可能存在一个令启发式混淆的问题。

+0

在鼠标事件和触摸事件触发的情况下,与preventDefault结合返回false应该在大多数(可能是所有)浏览器中修复它。 – logic8

+0

是的,这似乎也适用于我们。我可以证实,在使用jQuery Mobile 1.4.2时,我们遇到了这种行为,并且将e.preventDefault()解决了我们的问题。 –

+2

太神奇了!在我的例子中,我把** e.preventDefault(); **放在'$('。selector')。on('click touchstart',function(e){})''function和magic happend中的所有动作之后。 W/o ** e.preventDefault(); ** touchstart事件导致双击/点击。谢谢你,男人! –

0

我发现在我的情况下,在我的页面容器中添加了data-role="page",可以防止点击事件被激发两次。

1
$("#buttonID").tap(function(event){ 
     if(localStorage.JQMGostClick == 0 || localStorage.JQMGostClick == "" || typeof(localStorage.JQMGostClick) === "undefined") 
      localStorage.JQMGostClick = 1; 
     else if(localStorage.JQMGostClick == 1){ 
      localStorage.JQMGostClick = 0; 
      return false; 
     } 
..... 
}); 

它为我,因为如果你使用的是移动环境那么很可能你使用的是一种存储

0

我经历过这样的事情之前,它的事实,我的形式是,是由于中没有内data-role="page"

我的建议是jQuery Mobile的HTML结构来包装你的代码,以便您能应该是这样的,而不是

<div data-role="page" class="ui-page ui-page-theme-a ui-page-active"> 
    <div class="ui-content"> 
    <div id="box"> 
     tapped me 
    </div> 
    <script type="text/javascript"> 
     $(document).ready(function() { 
      $('#box').bind('tap',function(event) { 
       alert('why'); 
      }); 
     }); 
    </script> 
    </div> 
</div> 
0

这可能不是最好的解决方案,只会在某些情况下起作用,但对于我来说,在点击事件开始后,立即将该元素的CSS“指针事件”设置为“无”。然后使用JS的setTimeout将“指针事件”在500ms后重置为自动。

对我来说,300ms对于Android设备来说足够了,但iPhone需要500ms来防止双击。

function yourEvent(evt){ 
 

 
    $(el).css('pointer-events', 'none'); 
 
    
 
    setTimeout(function(){ 
 
     $(el).css('pointer-events', 'auto'); 
 
    }, 500); 
 
    
 
    //do you stuff 
 

 
}

2
这个问题相关的

,我得到两个事件“水龙头”和“点击”只是一个另一个之后。这里的所有想法都令人鼓舞,但我最终找到了另一种解决方案。我将下面的代码添加到JavaScript控制器中,以便根据时间戳区分连续的重复事件,幸运的是,两次重复事件完全相同。基本上,如果我决定使用事件,我所做的就是存储上次使用的时间戳。第二次有同样的时间戳我放弃了它。

var _lastEventTimestamp; 
 
var checkAndPreventDuplicatedEvent = function (e) { 
 
    if (e.timeStamp === _lastEventTimestamp) return true; 
 
    else _lastEventTimestamp = e.timeStamp; 
 
    return false; 
 
}

然后,在我的每个处理器的我在一开始加入这个过滤代码:

var onTapSomething = function (e) { 
 
    if (checkAndPreventDuplicatedEvent(e)) return;   
 
    //do here whatever you would do in the case of legitimate event... 
 
}

+0

多一个,你可以使用相同的策略,以摆脱一些“噪音”事件,以防万一。我在Android上遇到了一些问题...我通过使用以前的过滤器的此修改版本来摆脱它:var checkAndPreventDuplicatedEvent = function(e){if((e。timeStamp - _lastEventTimestamp)<1000)返回true; else _lastEventTimestamp = e.timeStamp; 返回false; } – pabloelustondo