2010-03-16 127 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详见。