2012-05-05 82 views
2

我有一個頁面需要定期切換div的可見性。問題是與父元素之一相關的點擊事件通常不會被調用。如果我停止了可見性切換或者如果我減慢它(例如300ms而不是100ms),點擊事件通常會被觸發。更改元素的可見性時不會調用事件

我已經創建了一個簡短的例子來說明這個問題。 你可以在這裏測試:http://threeds.me/0xC0DE/

點擊藍色/紅色方塊理論上應該點燃事件。當沒有動畫(默認行爲在這裏)點擊藍色方塊將始終觸發onclick事件。如果點擊「播放/暫停」,紅色方塊的可見性將開始每100毫秒切換一次。當動畫播放時,點擊事件不會在每次點擊廣場時調用。

我會懷疑,改變可見性是在某種程度上搞亂了DOM,結果停止了幾毫秒的事件。我還嘗試切換CSS可見性屬性以儘量減少對頁面的影響,但它具有相同的結果。

但這不僅是事件。如果我將整個容器封裝在一個標籤中,單擊該元素將不會被瀏覽器始終考慮在內。所以就像改變一個子元素的可見性會讓父母在相當一段時間內失明,這讓我覺得很奇怪。

這個問題與Firefox,Chrome和Opera(所有在Mac上都不能測試ie)是一致的,所以這意味着我沒有得到。所以,即使我沒有得到解決方案,我想了解問題所在。

這裏的來源爲您的即時參考

<!DOCTYPE html> 
<html> 
<head><title>Wiggle problem</title> 
<style> 
#dback { 
    width: 200px; 
    height: 200px; 
    background-color: red; 
} 
#dfront { 
    width: 200px; 
    height: 200px; 
    background-color: blue; 
} 
</style> 

<script type="text/javascript"> 
var run = false; 
function playpause() { 
    if (run) { 
     run = false; 
    } else { 
     run = true; 
     update(); 
    } 
} 

function update() { 
    if (run==false) { 
     return; 
    } 

    var el = document.getElementById('dfront'); 
    if (el.style.display != 'none') { 
     el.style.display = 'none'; 
    } 
    else { 
     el.style.display = ''; 
    } 

    setTimeout("update();", 100); 
} 
</script> 

</head> 

<body> 
<a href="#" onclick="playpause();">play/pause</a> 
<div id="container" onclick="d=new Date();t=d.getTime();document.getElementById('info').innerText='click '+t;"> 
    <div id="dback"> 
     <div id="dfront"></div> 
    </div> 
</div> 
<span id="info"></span> 
</body> 
</html> 

回答

0

這真的很奇怪!不過,我做了一些testsfiddled with your code一點,現在我認爲它與冒泡無關(你可以在我的測試中看到點擊visibility: hidden泡泡的元素就好了)。

這是我認爲可以回事:因爲你的計時器的時間間隔很短,沒有足夠的時間用於實際點擊註冊–點擊是一個mousedown事件,接着是mouseup事件,在同一個元素上。你的情況會發生什麼,mouseup經常被其他元素觸發,與解僱mousedown不同,因此沒有click事件。看到上面的第二個鏈接,我將間隔減少到1秒,然後嘗試單擊藍色方塊,然後釋放紅色方塊上的鼠標按鈕(反之亦然)。什麼都沒發生。我可能完全錯誤,但看起來似乎有道理。

我知道這是不是一個解決辦法,但你說:

所以,即使我沒有得到一個解決方案,我想知道是什麼問題。

我希望這可以幫助您找到一個!

最後但並非最不重要的,在你的代碼中的幾個側面說明:

  1. 不建議你打電話setTimeout(傳遞字符串)的方式,因爲它會強制使用eval內部,並儘可能地使用eval should be avoided。相反,傳遞字符串的函數調用代碼,只是通過函數本身:

    setTimeout(update, 100); 
    
  2. 它認爲是當今最好的做法是使用addEventListener(或attachEvent用於IE)將事件綁定到一個元素,而不是使用內聯事件,如onclick="..."。這有幾個優點,例如幫助分離行爲,結構和佈局,並使事件對象自動用於事件處理程序(作爲處理函數的第一個參數)。

+0

謝謝bfavaretto。我想你是對的。這是邏輯,可以解釋爲什麼這在所有瀏覽器上都是一致的,即使在鏈接上也是如此。我也很欣賞這個建議。很好的幫助! – NicMagnier

0

Acctually,當「dfront」是可見的,它懸停在「容器」,而當你點擊,事件變爲「dfront」。但沒有onclick事件,因爲「dfront」元素。 「容器」的Onclick事件不會在子元素上傳播 - 正常情況下,您可以通過使用jquery解決它,它具有事件傳播的「事件傳播」選項。 或者只設置「dfront」的onclick事件。

此外,您可以通過「容器」和「dfront」創建透明層並將事件綁定到它。 或者,在窗口對象上創建onmouseclick事件,通過檢查它們的座標,如果鼠標位置在「dfront」上方,將會發現事件處理程序將被觸發。

+0

默認#dfront是可見的,在#container的onclick事件正確解僱,因爲該事件被傳播到父母直到一個元素停止傳播。問題似乎是切換可見性會影響這種傳播。我在考慮使用你提到的一些解決方法,但在做之前我想確保我理解這個問題。 – NicMagnier

+0

@Denis,傳播不是一個jQuery特性,它實際上是DOM實現的一部分,並且在純js(以及停止事件傳播的機制)中可用。 – bfavaretto

相關問題