检测/监控 DOM 变化的最有效方法?

IT技术 javascript dom mutation-events mutation-observers
2021-01-24 07:01:20

我需要一种有效的机制来检测 DOM 的变化。最好是跨浏览器,但如果有任何不是跨浏览器的有效方法,我可以使用故障安全的跨浏览器方法来实现这些。

特别是,我需要检测会影响页面上文本的更改,因此需要任何新的、删除的或修改的元素,或者对内部文本 (innerHTML) 的更改。

我无法控制所做的更改(它们可能是由于 3rd 方 javascript 包含等),因此无法从这个角度进行处理 - 我需要以某种方式“监视”更改。

目前我已经实现了一个“quick'n'dirty”的方法,它body.innerHTML.length每隔一段时间检查一次这当然不会检测到导致返回相同长度的更改,但在这种情况下“足够好” - 这种情况发生的可能性非常小,并且在这个项目中,无法检测到更改将不会导致在丢失的数据中。

问题body.innerHTML.length是它很贵。快速浏览器上它可能需要 1 到 5 毫秒,这可能会使事情陷入困境 - 我也在处理大量的 iframe,而且所有这些都会加起来。我很确定这样做的代价是因为innerHTML 文本不是由浏览器静态存储的,每次读取时都需要从DOM 计算。

我正在寻找的答案类型是从“精确”(例如事件)到“足够好”的任何东西 - 也许像 innerHTML.length 方法一样“快速”和“肮脏”,但执行速度更快。

编辑:我还应该指出,虽然检测已修改的精确元素会“很好”,但这并不是绝对必要的——只要有任何变化就足够了。希望这能扩大人们的react。我将调查 Mutation Events,但我仍然需要对 IE 支持的后备,所以任何古怪的、有创意的、不合时宜的想法都会受到欢迎。

6个回答

为了更新这一点,DOM4 标准取消了 Mutation Events 并用 Mutation Observers 取而代之:https : //developer.mozilla.org/en-US/docs/Web/API/MutationObserver

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

jQuery 现在支持一种将事件附加到与选择器对应的现有和未来元素的方法:http : //docs.jquery.com/Events/live#typefn

另一个有趣的发现 - http://james.padolsey.com/javascript/monitoring-dom-properties/

jQuery 的live()方法在 IE 中似乎不是最好的,所以我也使用标准bind() (然后unbind().bind()在添加任何新内容的情况下进行任何更改),但是使用 DOMTree 事件以及onPropertyChange和 setInterval 回退,似乎做到这一点。watch()看起来太麻烦了(必须手动添加到所有元素,因为它不是标准事件类型,它只是一种方法),而且我不确定各种浏览器是否正确支持它,而其他两种方法似乎涵盖大多数基地。
2021-03-21 07:01:20
谢谢,这似乎涵盖了所有基础 - 非 IE 和onPropertyChangeIE 的DOMTree 事件我尚未实施该onPropertyChange活动,但会实施- 请参阅我对 @Gaby 帖子的评论,了解迄今为止所做工作的最新情况。
2021-03-30 07:01:20
仅供参考:“从 jQuery 1.7 开始,.live() 方法已被弃用。使用 .on() 附加事件处理程序。旧版本的 jQuery 用户应优先使用 .delegate() 而不是 .live()。” 来自文档
2021-04-05 07:01:20
补充一下:mozilla 文档说观察突变事件已被弃用,应替换为“突变观察者”。不过,我不知道突变观察者是否完全可用。
2021-04-12 07:01:20

突变事件是您正在寻找的 W3 推荐。

不确定它们是否得到全面支持..(IE 很可能不支持它们..)

我现在正在使用这些事件 - 我仍在按body.innerHTML.length设定的时间间隔检查,但是如果触发了这些事件中的任何一个,我假设不再需要定期检查并将其关闭。我仍在调查onPropertyChangewatch()作为替代方案,并且可能会使用类似的想法来实现这些,因为如果它们被触发,我可以取消任何其他检查 -onPropertyChange可能适用于 IE 但不适用于其他浏览器。
2021-04-01 07:01:20
Mutation 事件目前已被弃用,以支持 Mutation Observers developer.mozilla.org/en-US/docs/Web/API/MutationObserver
2021-04-11 07:01:20

您可以尝试使用 DOMNodeInserted 和 DOMNodeRemoved 事件。根据 Quirksmode,它们可以在大多数浏览器中工作,但 IE 除外……

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

它们是 DOM 级别 2 中引入的两种 Mutation Event 类型。还有一些事件类型存在。
2021-04-12 07:01:20

我最近写了一个插件就是这样做的 - 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 上工作,依赖项详见自述页面