有没有JavaScript / jQuery DOM更改侦听器?

基本上我想在DIV的内容发生变化时执行一个脚本。 由于脚本是分开的(在Chrome扩展和网页脚本中的内容脚本),我需要一种方式来简单地观察DOM状态的变化。 我可以设置投票,但似乎马虎。

这个答案的旧内容现在已被弃用 。
查看基于MutationObserver的其他答案。

几年之后,现在正式有了一个更好的解决scheme。 DOM4突变观察者是不推荐使用的DOM3突变事件的替代品。 它们目前在现代浏览器中被实现为MutationObserver (或作为老版本的Chrome中的供应商加前缀的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 //... }); 

这个例子监听document及其整个子树上的DOM更改,并且会触发对元素属性的更改以及结构更改。 草案规范有一个有效的突变监听器属性的完整列表:

的childList

  • 如果要对目标儿童进行突变,则设为true

属性

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

characterData

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

子树

  • 设置为true如果突变不只是目标,而且目标的后代要观察。

attributeOldValue

  • 如果attributes设置为true,并且在需要logging突变之前的目标属性值,则设置为true。

characterDataOldValue

  • 如果characterData设置为true,并且需要logging突变之前的目标数据,则设置为true。

attributeFilter

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

(这份清单是截至2014年4月的最新清单;您可以查看规范是否有任何更改。)

另一种方法取决于你如何改变分区。 如果你正在使用JQuery来改变一个div的html()方法的内容,那么你可以扩展这个方法,并在每次把div放入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期望它用于方法链接。

有关方法重写和扩展的更多信息,请查看http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm ,这是哪里我打开了closuresfunction。 还请查看JQuery网站上的插件教程。

许多网站使用AJAXdynamic添加/显示/更改内容。 有时使用它来代替现场导航,因此当前的URL以编程方式更改,并且浏览器不会自动执行内容脚本,因为该页面不是从远程服务器完全获取的。


常见的JS方法检测内容脚本中可用的页面更改。

  • MutationObserver ( docs )从字面上检测DOM变化:

    • 在页面加载时如何更改HTML内容
    • MutationObserver检测整个DOM中的节点的性能 。
  • 通过发送DOM事件发送内容更改的站点的事件侦听器:

    • pjax:end许多基于pjax的站点使用的document ,例如GitHub,
      请参阅如何在pjax加载之前和之后运行jQuery?
    • Chrome浏览器中Googlesearch所使用的window message
      请参阅Chrome扩展程序检测Googlesearch刷新
    • spfdone在Youtube使用的document上,
      请参阅如何检测Youtube上的页面导航并在页面呈现之前修改HTML?
  • 通过setInterval定期检查DOM
    显然,只有在等待由其id /select器标识的特定元素出现的情况下,它才会起作用,除非您发明某种指纹化现有内容,否则不会让您通用检测到新的dynamic添加的内容。

  • 在注入的DOM脚本中隐藏历史loggingAPI :

     document.head.appendChild(document.createElement('script')).text = '(' + function() { // injected DOM script is not a content script anymore, // it can modify objects and functions of the page var _pushState = history.pushState; history.pushState = function(state, title, url) { _pushState.call(this, state, title, url); window.dispatchEvent(new CustomEvent('state-changed', {detail: state})); }; // repeat the above for replaceState too } + ')(); this.remove();'; // remove the DOM script element // And here content script listens to our DOM script custom events window.addEventListener('state-changed', function(e) { console.log('History state changed', e.detail, location.hash); doSomething(); }); 
  • 聆听hashchange , popstate事件:

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


特定于扩展:检测后台 / 活动页面中的 URL更改。

有一些高级API可用于导航: webNavigation , webRequest ,但我们将使用简单的chrome.tabs.onUpdated事件侦听器向内容脚本发送消息 :

  • manifest.json的:
    申报背景/活动页面
    声明内容脚本
    添加"tabs" 权限 。

  • background.js

     var rxLookfor = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/; chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if (rxLookfor.test(changeInfo.url)) { chrome.tabs.sendMessage(tabId, 'url-update'); } }); 
  • content.js

     chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) { if (msg === 'url-update') { doSomething(); } }); 

除了MutationObserver API提供的“原始”工具外,还有“便利”库来处理DOM突变。

考虑:MutationObserver以子树的forms表示每个DOM变化。 所以,如果你正在等待插入一个特定的元素,它可能会深入到mutations.mutation[i].addedNodes[j]

另一个问题是,当你自己的代码,对突变的反应,改变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); }