2012-05-29 150 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