2012-02-28 109 views
17

是否有可能以及如何使用jQuery監聽整個DOM樹的更改?jQuery:如何監聽DOM更改?

我的具體問題:我有一個'工具提示'功能,當您對任何html元素執行hover時,會以一種時尚的方式顯示title屬性的內容。但是,當您執行懸停時,瀏覽器會根據標準將title顯示在其自己的框中。我想抑制這一點。所以我想到的是在第一次加載頁面時將title屬性的內容移動到自定義(HTML5)data-title屬性,然後我的工具提示功能將與data-title一起使用。

問題是,稍後我可能會動態地添加/刪除/更改HTML,因此我需要'重新綁定'這些元素 - 再次更改這些標題attrs。如果有一個事件監聽器會爲我監聽這樣的更改並自動重新綁定這些元素,那將會很好。

+0

可能重複【如何當DOM已被更改標識?](http://stackoverflow.com/questions/3744706/how-to-identify-when-the -dom-has-been-changed) – 2012-02-28 19:53:30

+2

好像試圖聽DOM中的每一個變化......並且每次搜索你的元素都會非常昂貴。 – charlietfl 2012-02-28 19:58:46

+0

可能的重複[是否有一個jQuery DOM更改偵聽器?](http://stackoverflow.com/questions/2844565/is-there-a-jquery-dom-change-listener) – APerson 2015-02-17 19:55:43

回答

33

我最好的猜測是,你要聽DOM突變事件。 您可以通過DOM突變事件來完成任何正常的JavaScript事件,如鼠標點擊。

請參閱本:W3 MutationEvent

實施例:

$("element-root").bind("DOMSubtreeModified", "CustomHandler"); 
+1

您不需要引號處理程序,它是讓函數綁定到事件的一種方法。 – MacMac 2012-02-28 20:23:33

+1

此代碼可能看起來簡短而甜蜜,但它在瀏覽器上的負載超出了以下事件代理解決方案存在的情況下的用例 – charlietfl 2012-02-28 22:14:43

+0

我的錯誤..我在短時間內添加了引號 – nightf0x 2012-02-29 05:09:56

2

因此,無需額外的代碼,這是一個比特的盲鏡頭的[在由構件託尼答覆研究編輯] ,但在我看來,這裏有兩點需要思考:1.默認的瀏覽器工具提示行爲; 2.可能更新的DOM以及自定義工具提示繼續運行的功能。

關於#1:當您將自定義事件綁定到元素時,可以使用event.preventDefault(),以便不出現工具提示。這不能正常工作。因此,繼續使用「title」屬性的解決方法是獲取該值,將其推入數據對象($.data()函數),然後用空字符串(removeAttr不一致)爲空標題。然後在mouseleave上,您從數據對象中獲取值並將其推回到標題中。這個想法來自這裏:How to disable tooltip in the browser with jQuery?

關於#2:而不是重新綁定DOM的變化,你只需要綁定一次從來沒有被期望銷燬的監聽器元素。通常這是某種類型的容器元素,但如果您真的需要一個包含所有容器的容器,它甚至可以是document(接近.live(),現在已被棄用)。下面是一個使用我自己設計的一些假標記的樣本:

var container = $('.section'); 

container.on('mouseenter', 'a', function() { 
    var $this = $(this); 
    var theTitle = $this.attr('title'); 
    $this.attr('title', ''); 
    $('#notatooltip').html(theTitle); 
    $.data(this, 'title', theTitle); 
}); 

container.on('mouseleave', 'a', function() { 
    $('#notatooltip').html(''); 
    var $this = $(this); 
    var storedTitle = $.data(this, 'title'); 
    $this.attr('title', storedTitle); 
}); 

我不現實的標記(只是在這個例子中)在這裏:

<div class="section"> 
    <a href="#" title="foo">Hover this foo!</a> 
    <div id="notatooltip"></div> 
</div> 

而小提琴是在這裏:http://jsfiddle.net/GVDqn/ 還是有一些理智檢查:http://jsfiddle.net/GVDqn/1/

有可能是一個更優化的方法來做到這一點(我真的沒有研究,如果你可以綁定兩個單獨的功能爲兩個單獨的事件與一個選擇器),但它會做的伎倆。

您不應該基於DOM更改重新綁定,委派的偵聽器會自動處理它。而且您應該可以通過防止默認的工具提示功能來防止它。

+0

這裏最明智的方法!....然後在鼠標中可以測試標題是否已被移動到$(this).data('標題')或不是 – charlietfl 2012-02-28 20:24:48

+0

將是最優雅的解決方案,但似乎'preventDefault'不會阻止在'mouseover'上顯示標題(至少在Chrome中) - http://code.google.com/p/chromium/issues/detail?id=42549 – 2012-02-28 21:03:41

+0

@Tony好找;我認爲Fx也是失敗的。我已經更新了新的代碼。 – 2012-02-28 22:01:27

0

正如Greg Pettit所述,您應該在元素上使用on()函數。

這樣做可以讓你將選擇器綁定到一個事件,然後當選擇器返回的對象可用時,jQuery將添加這個事件處理器。

如果你想要一個功能火上鼠標事件,你希望它火的所有元素與類的* FIELD_TITLE *你可以這樣做:

$('.field_title').bind('mouseenter', function() { doSomething(); }); 

這將觸發在類別爲* field_title *並執行函數doSomething()的任何對象上的鼠標懸停事件。

希望是有道理的:)

+1

你有一個錯字,應該是'.bind('mouseenter')'不是'。('mouseenter')'。 – MacMac 2012-02-28 20:24:10