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

是否有JavaScript/jQuery DOM更改侦听器?,javascript,jquery,google-chrome-extension,Javascript,Jquery,Google Chrome Extension,本质上,我希望在DIV的内容更改时执行脚本。由于这些脚本在Chrome扩展和网页脚本中是独立的内容脚本,所以我需要一种方法来简单地观察DOM状态的变化。我可以设置轮询,但这似乎有些草率。Edit 这个答案现在已被弃用。请看下面的答案 因为这是一个Chrome扩展,所以您最好使用标准的DOM事件-DOMSubtreeModified。请参阅跨浏览器对此的支持。Chrome从1.0开始就支持它 $("#someDiv").bind("DOMSubtreeModified", function() {

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

Edit

这个答案现在已被弃用。请看下面的答案

因为这是一个Chrome扩展,所以您最好使用标准的DOM事件-DOMSubtreeModified。请参阅跨浏览器对此的支持。Chrome从1.0开始就支持它

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

请参阅一个工作示例。

另一种方法取决于您如何更改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的调用,用它调用注册函数,在上下文中,注册函数指的是目标元素获得新内容,然后我们将调用传递给原始jquery.html函数。记住返回原始html方法的结果,因为JQuery希望它用于方法链接


有关方法重写和扩展的更多信息,请查看,这是我创建闭包函数的地方。还可以在JQuery的站点上查看插件教程。

很长一段时间以来,DOM3突变事件是最好的解决方案,但由于性能原因,它们一直被弃用。是不推荐的DOM3突变事件的替代品。它们与旧版Chrome中的MutationObserver或供应商前缀WebKitMutationObserver相同:

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
  //...
});
此示例侦听文档及其整个子树上的DOM更改,并在元素属性更改和结构更改时触发。规范草案包含以下有效规范的完整列表:

儿童名单

如果要观察到目标儿童的突变,则设置为true。 属性

如果要观察到目标属性的突变,则设置为true。 字符数据

如果要观察到目标数据的突变,则设置为true。 子树

如果不仅要观察到目标基因的突变,而且要观察到目标基因的后代,则设置为true。 属性值

如果属性设置为true,并且需要记录突变前目标的属性值,则设置为true。 characterDataOldValue

如果characterData设置为true并且需要记录突变前的目标数据,则设置为true。 属性过滤器

如果不需要观察所有属性突变,则设置为不带命名空间的属性本地名称列表。
该列表截至2014年4月为最新列表;您可以检查规范是否有任何更改。

除了提供的原始工具外,还有一些方便的库可用于处理DOM突变

考虑:MutationObserver用子树表示每个DOM更改。例如,如果你在等待某个元素被插入,它可能深入到突变的子元素中。突变[i].附加节点[j]

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

一个很好的解决这些问题的便利库是免责声明:我不是作者,只是一个满意的用户,它使您能够指定您感兴趣的查询,并准确地得到它

文档中的基本用法示例:

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);
}

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

检测页面更改的常用JS方法 使用MutationObserver检测DOM更改:

简单的例子:

让lastUrl=location.href; 新变种观察者=>{ const url=location.href; 如果url!==lastUrl{ lastUrl=url; 变革; } }.observedocument,{subtree:true,childList:true}; 功能变化{ console.log'URL changed!',location.href; } 通过发送DOM事件发出内容更改信号的站点的事件侦听器:

pjax:许多基于pjax的站点(如GitHub)使用的端到端文档, 看见 在Chrome浏览器中谷歌搜索所使用的窗口上的消息, 看见 yt被Youtube使用, 看见 通过setInterval定期检查DOM: 显然,这只在等待由id/选择器标识的特定元素出现的情况下起作用,并且它不会让您全面检测新的动态添加内容,除非您对现有内容发明某种指纹

斗篷:

让_pushState=History.prototype.pushState; History.prototype.pushState=函数状态、标题、url{ _pushState.callthis,state,title,url; 控制台。日志“URL已更改”,URL }; 收听、活动:

window.addEventListener'hashchange',e=>{ log'URL hash changed',e; 剂量测定法; }; window.addEventListener'popstate',e=>{ console.log'State changed',e; 剂量测定法; };
另外,所有这些方法都可以在WebExtension中使用。这是因为我们正在研究的情况是,URL通过history.pushState或replaceState更改,因此页面本身在相同的内容脚本环境下保持不变。

我注意到,即使在某些选择器之后,也可以触发此事件。我正在调查。表示此事件已被弃用,我们将使用什么替代?@Maslow-没有!对于jquery用户来说,有一个基本上可以解决这个问题的方法。如果你正在构建chrome扩展,这个方法仍然有效。无价之宝。@AshrafBashir我看到该示例在Firefox 19.0.2中运行良好:我看到[{}]登录到控制台,当我单击它时,它显示预期的MutationRecord。请再次检查,因为这可能是JSFIDLE中的临时技术故障。我还没有在IE中测试过它,因为我没有IE 10,它是目前唯一支持突变事件的版本。我刚刚发布了一个答案,该答案适用于IE10+和其他任何版本。该规范似乎不再有一个列出突变观察者选项的绿色框。它在第5.3.1节中有介绍,并在下面进行了进一步描述。@LS谢谢,我已经更新了链接,删除了关于绿色框的部分,并将整个列表编辑到我的答案中,以防将来链接出现问题。我可以使用吗?这回答了你的问题吗?