是否有 JavaScript / jQuery DOM 更改侦听器?

IT技术 javascript jquery google-chrome-extension
2020-12-16 00:56:32

本质上,我希望在内容DIV更改时执行脚本由于脚本是独立的(Chrome 扩展程序和网页脚本中的内容脚本),我需要一种方法来简单地观察 DOM 状态的变化。我可以设置投票,但这似乎很草率。

5个回答

长期以来,DOM3 突变事件是最好的可用解决方案,但由于性能原因,它们已被弃用。DOM4 Mutation Observers是已弃用的 DOM3 突变事件的替代品。它们目前在现代浏览器中实现MutationObserver(或作为WebKitMutationObserver旧版 Chrome 中的供应商前缀):

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    console.log(mutations, observer);
    // ...
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

此示例侦听 DOMdocument及其整个子树的更改,并将触发元素属性的更改以及结构的更改。规范草案有一个完整的有效突变监听器属性列表

子列表

  • true如果要观察目标孩子的突变设置为

属性

  • true如果要观察目标属性的突变设置为

字符数据

  • true如果要观察目标数据的突变设置为

子树

  • 设置为trueif 突变不仅要观察目标,还要观察目标的后代。

属性旧值

  • 设置为trueif attributes,设置为true,需要记录突变前target的属性值。

字符数据旧值

  • 设置为trueifcharacterData设置为 true 并且需要记录突变之前的目标数据。

属性过滤器

  • 如果不需要观察所有属性突变,则设置为属性本地名称列表(没有命名空间)。

(此列表截至 2014 年 4 月是最新的;您可以查看规范以了解任何更改。)

2021-02-12 00:56:32
@LS 谢谢,我已经更新了链接,删除了关于绿框的部分,并将整个列表编辑到我的答案中(以防将来链接失效)。
2021-02-18 00:56:32
@AshrafBashir 我看到示例在 Firefox 19.0.2 中工作正常:我看到([{}])登录到控制台,MutationRecord当我点击它时显示预期请再次检查,因为它可能是 JSFiddle 中的临时技术故障。我还没有在 IE 中测试它,因为我没有 IE 10,它是目前唯一支持突变事件的版本。
2021-03-05 00:56:32
我刚刚发布了一个适用于 IE10+ 和其他大部分内容的答案。
2021-03-06 00:56:32
该规范似乎不再有一个绿色框来列出突变观察者选项。它确实列出了5.3.1 节中的选项,并在其下方进一步描述了它们。
2021-03-08 00:56:32

编辑

此答案现已弃用。请参阅apsillers的答案

由于这是针对 Chrome 扩展程序,您不妨使用标准的 DOM 事件 - DOMSubtreeModified查看跨浏览器对此事件的支持Chrome 从 1.0 开始就支持它。

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("tree changed");
});

请参阅此处的工作示例

github.com/joelpurra/jquery-mutation-summary基本上为 jquery 用户解决了它。
2021-02-07 00:56:32
如果您正在构建 chrome 扩展程序,它仍然有效。无价。
2021-02-15 00:56:32
2021-02-16 00:56:32
我注意到即使在某些选择器之后也可以触发此事件。我目前正在调查。
2021-02-27 00:56:32
w3.org/TR/DOM-Level-3-Events/#event-type-DOMSubtreeModified说这个事件已被弃用,我们会用什么代替?
2021-03-04 00:56:32

许多站点使用 AJAX/XHR/fetch 来动态添加、显示、修改内容和 window.history API 而不是站点内导航,因此当前 URL 以编程方式更改。此类站点称为 SPA,单页应用程序的缩写。


检测页面变化的常用JS方法

  • MutationObserver ( docs ) 从字面上检测 DOM 更改:

  • 通过发送 DOM 事件来指示内容更改的站点的事件侦听器:

  • 通过 setInterval 定期检查 DOM
    显然,这仅在您等待由其 id/选择器标识的特定元素出现的情况下才有效,并且除非您发明某种指纹识别,否则它不会让您普遍检测新的动态添加的内容现有的内容。

  • 伪装历史API

    let _pushState = History.prototype.pushState;
    History.prototype.pushState = function (state, title, url) {
      _pushState.call(this, state, title, url);
      console.log('URL changed', url)
    };
    
  • 监听hashchange , popstate事件:

    window.addEventListener('hashchange', e => {
      console.log('URL hash changed', e);
      doSomething();
    });
    window.addEventListener('popstate', e => {
      console.log('State changed', e);
      doSomething();
    });
    

PS 所有这些方法都可以在 WebExtension 的内容脚本中使用这是因为我们正在研究的情况是通过 history.pushState 或 replaceState 更改 URL 的情况,因此页面本身在相同的内容脚本环境下保持不变。

另一种方法取决于您如何更改 div。如果您使用 JQuery 通过其 html() 方法更改 div 的内容,则可以扩展该方法并在每次将 html 放入 div 时调用注册函数。

(function( $, oldHtmlMethod ){
    // Override the core html method in the jQuery object.
    $.fn.html = function(){
        // Execute the original HTML method using the
        // augmented arguments collection.

        var results = oldHtmlMethod.apply( this, arguments );
        com.invisibility.elements.findAndRegisterElements(this);
        return results;

    };
})( jQuery, jQuery.fn.html );

我们只是拦截对 html() 的调用,用 this 调用一个注册函数,它在上下文中指的是目标元素获取新内容,然后我们将调用传递给原始的 jquery.html() 函数。请记住返回原始 html() 方法的结果,因为 JQuery 期望它用于方法链接。

有关方法覆盖和扩展的更多信息,请查看http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm,这是我写了闭包函数。还可以查看 JQuery 站点上的插件教程。

除了MutationObserverAPI提供的“原始”工具之外,还存在处理 DOM 突变的“便利”库。

考虑: MutationObserver 代表子树方面的每个 DOM 更改。因此,例如,如果您正在等待插入某个元素,它可能在mutations.mutation[i].addedNodes[j].

另一个问题是,当您自己的代码对突变做出react时,更改了 DOM - 您通常希望将其过滤掉。

一个很好的解决此类问题的便利库是mutation-summary(免责声明:我不是作者,只是一个满意的用户),它使您能够指定对您感兴趣的内容的查询,并得到准确的结果。

文档中的基本用法示例:

var observer = new MutationSummary({
  callback: updateWidgets,
  queries: [{
    element: '[data-widget]'
  }]
});

function updateWidgets(summaries) {
  var widgetSummary = summaries[0];
  widgetSummary.added.forEach(buildNewWidget);
  widgetSummary.removed.forEach(cleanupExistingWidget);
}