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

本质上,我希望在DIV的内容发生变化时执行脚本。由于脚本是分开的(内容脚本在Chrome扩展&网页脚本),我需要一种方法简单地观察DOM状态的变化。我可以设置民意调查,但这看起来很草率。

340975 次浏览

编辑

这个答案现在已弃用。参见apsillers的答案。

由于这是一个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()的调用,用this调用一个注册函数,它在上下文中指的是获取新内容的目标元素,然后我们将调用传递给原始的jquery.html()函数。记住要返回原始html()方法的结果,因为JQuery期望它用于方法链接。

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

在很长一段时间里,DOM3突变事件是可用的最佳解决方案,但由于性能原因,它们已被弃用。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,并且需要记录突变之前的目标属性值,则设置为true

characterDataOldValue

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

attributeFilter

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

(此列表截至2014年4月;如有任何更改,请查阅说明书。)

除了MutationObserver API提供的“原始”工具外,还有一些“方便”库可以处理DOM突变。

考虑:MutationObserver以子树的形式表示每个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);
}

许多网站使用AJAX/XHR/fetch来动态添加、显示、修改内容和窗口。历史API,而不是在网站导航,所以当前的URL被编程改变。这样的网站被称为SPA,是单页应用程序的缩写。


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

  • MutationObserver (文档)字面上检测DOM更改。

    信息/例子:

  • 事件监听器对于通过发送DOM事件来表示内容变化的站点:

  • <李> < p > 通过setInterval定期检查DOM:
    显然,这只在你等待一个由id/selector标识的特定元素出现的情况下才会起作用,并且它不会让你普遍检测到新的动态添加的内容,除非你发明某种现有内容的指纹
  • < p > Cloaking 历史API:

    let _pushState = History.prototype.pushState;
    History.prototype.pushState = function (state, title, url) {
    _pushState.call(this, state, title, url);
    console.log('URL changed', url)
    };
    
  • < p > 收听hashchangepopstate events:

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

附注:所有这些方法都可以在webeextension的内容脚本中使用。这是因为我们正在查看的情况是通过历史记录更改URL的情况。pushState或replaceState,这样页面本身在相同的内容脚本环境中保持不变。