2010-03-16 86 views
41

我需要一個有效的機制來檢測DOM的變化。最好是跨瀏覽器,但如果有任何有效的手段,而不是跨瀏覽器,我可以實現這些與一個故障安全跨瀏覽器方法。檢測/監測DOM變化的最有效方法?

特別是,我需要檢測會影響頁面上文本的更改,因此需要任何新的,刪除或修改的元素,或更改內部文本(innerHTML)。

我無法控制所做的更改(它們可能是由於第三方JavaScript包括等),所以無法從這個角度來處理 - 我需要以某種方式「監視」更改。

目前我實施了一個「quick'n'dirty」方法,每隔一段時間檢查body.innerHTML.length。這當然不會檢測到導致返回相同長度的變化,但在這種情況下「足夠好」 - 發生這種情況的可能性非常小,並且在該項目中,未能檢測到變化將不會導致丟失數據。

body.innerHTML.length的問題是它很貴。在快速瀏覽器上,它可能需要1到5毫秒的時間,這可能會讓事情變得很糟糕 - 我也在處理大量的iframe,並且這些都會加起來。我很確定這樣做的代價很大,因爲innerHTML文本不是由瀏覽器靜態存儲的,每次讀取時都需要從DOM中計算。

我正在尋找的答案類型是從「精確」(例如事件)到「足夠好」的任何內容 - 可能與innerHTML.length方法一樣,是「quick'n'dirty」,但是執行得更快。

編輯: 我還要指出的是,雖然這將是「好」來檢測已被修改的精確元素,它不是絕對必要的 - 只是一個事實,即出現了任何變化是夠好了。希望這可以擴大人們的反應。我要去調查突變事件,但我仍然需要IE支持的後備,所以任何拙劣的,有創意的,不尋常的想法都會受到歡迎。

+0

上次這個問題沒有太多運氣:http://stackoverflow.com/questions/648996/how-do-i-monitor-the-dom-for-changes – 2010-03-16 20:01:49

+0

是的,我看到了,你是對...沒有太多的運氣。 *但是*,因爲我不需要100%的準確性,也因爲我不需要指出哪個元素已經改變,只是*有*改變,我希望人們想出一些創造性的解決方案對我來說... – Graza 2010-03-17 10:31:51

+0

[是否有JavaScript/jQuery DOM更改偵聽器?](https://stackoverflow.com/questions/2844565/is-there-a-javascript-jquery-dom-change-listener) – Makyen 2017-10-28 09:21:25

回答

9

http://www.quirksmode.org/js/events/DOMtree.html

的jQuery現在支持的方式來將事件附加到現有的和對應未來元素選擇:http://docs.jquery.com/Events/live#typefn

另一個有趣的發現 - http://james.padolsey.com/javascript/monitoring-dom-properties/

+0

謝謝,這似乎涵蓋了所有的基礎 - 非IE的DOMTree事件和IE的'onPropertyChange'。我還沒有實現'onPropertyChange'事件,但會 - 看到我對@ Gaby的帖子的評論,以更新迄今爲止已完成的內容。 – Graza 2010-03-18 10:21:06

+0

jQuery的'live()'方法在IE中看起來並不是最好的,所以我也使用標準的'bind()'(然後是'unbind()。bind已被添加),但使用DOMTree事件,以及'onPropertyChange'和一個setInterval回退,似乎有訣竅。 'watch()'似乎太麻煩了(必須手動添加到所有元素,因爲它不是標準的事件類型,它只是一種方法),我不確定它在各種瀏覽器中是否得到正確支持,而另一個兩種方法似乎涵蓋了大多數基地。 – Graza 2010-03-18 18:14:05

+2

僅供參考:「從jQuery 1.7開始,不推薦使用.live()方法。使用.on()附加事件處理程序。老版本jQuery的用戶應該優先使用.delegate(),而不是.live()。「[來自文檔](http://api.jquery.com/live/#typefn) – 2012-06-29 22:58:09

7

Mutation events是你在找什麼的W3建議..

不知道他們周圍都支持。(IE將最有可能不支持他們。)

+0

我現在正在使用這些事件 - 我仍然按照設定的時間間隔檢查'body.innerHTML.length',但是如果這些事件中的任何一個被觸發,我會假設不再需要定期檢查,並將其變爲關閉。我仍然在研究'onPropertyChange'和'watch()'作爲替代品,並且可能會使用類似的想法來實現這些功能,因爲如果它們被觸發,我可以取消任何其他檢查 - onPropertyChange'可能在IE中工作,但是不是其他瀏覽器。 – Graza 2010-03-18 10:17:50

+0

突變事件目前不推薦使用Mutation Observers https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver – 2014-08-29 12:59:10

1

你可以嘗試使用DOMNodeInserted和DOMNodeRemoved事件。 Acording到怪異模式,他們那種在大部分瀏覽器,使用IE的顯着的例外......

http://www.quirksmode.org/dom/events/index.html

+0

它們是DOM級別2中引入的兩種突變事件類型。少數更多的事件類型存在.. – 2010-03-16 18:41:47

1

我最近寫了一個插件確實如此 - jquery.initialize

您使用它的方式與.each功能

$(".some-element").initialize(function(){ 
    $(this).css("color", "blue"); 
}); 

的差異從.each是 - 它需要你的選擇,在這種情況下.some-element並等待此選擇在未來新的元素,如果這些元素將被添加,它也將被初始化。

在我們的例子中,初始化函數只是將元素的顏色更改爲藍色。所以,如果我們像(如果使用Ajax,甚至F12檢查或任何不論)添加新的元素:

$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color! 

插件會立即初始化它。插件也確保一個元素只被初始化一次。所以,如果你添加元素,然後從身體.deatch(),然後再添加它,它不會被再次初始化。

$("<div/>").addClass('some-element').appendTo("body").detach() 
    .appendTo(".some-container"); 
//initialized only once 

插件是基於MutationObserver - 這將依賴於IE9工作,10對readme page詳見。