提问人:Fletcher Moore 提问时间:5/17/2010 最后编辑:MikeFletcher Moore 更新时间:1/19/2022 访问量:357217
是否有 JavaScript / jQuery DOM 更改侦听器?
Is there a JavaScript / jQuery DOM change listener?
问:
从本质上讲,我希望在更改内容时执行脚本。由于脚本是分开的(Chrome扩展和网页脚本中的内容脚本),我需要一种方法来简单地观察DOM状态的变化。我可以设置轮询,但这似乎很草率。DIV
答:
编辑
此答案现已弃用。请看apsillers的答案。
由于这是针对 Chrome 扩展程序的,因此您不妨使用标准的 DOM 事件 - 。请参阅跨浏览器对此事件的支持。自 1.0 以来,Chrome 一直支持它。DOMSubtreeModified
$("#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 期望它用于方法链接。
有关方法覆盖和扩展的更多信息,请查看 http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm,这是我使用闭包函数的地方。另请查看 JQuery 网站上的插件教程。
在很长一段时间里,DOM3 突变事件是最好的解决方案,但由于性能原因,它们已被弃用。DOM4 突变观察器是已弃用的 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 及其整个子树的更改,并将在元素属性更改以及结构更改时触发。规范草案包含有效突变侦听器属性的完整列表:document
儿童名单
- 设置为如果要观察到目标子项的突变。
true
属性
- 设置为如果要观察到目标属性的突变。
true
字符数据
- 设置为如果要观察到目标数据的突变。
true
子树
- 设置为 if 突变不仅针对目标,还针对目标的后代。
true
属性OldValue
- 设置为 if 时,设置为 true 和 target 的属性值,然后才需要记录突变。
true
attributes
字符数据旧值
- 设置为 if 设置为 true,并且需要记录突变之前的目标数据。
true
characterData
attributeFilter(属性过滤器)
- 如果不是所有属性突变都需要观察,则设置为属性本地名称列表(不带命名空间)。
(此列表是截至 2014 年 4 月的最新列表;您可以查看规范是否有任何更改。
评论
([{}])
MutationRecord
除了 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 来动态添加、显示、修改内容,并使用 window.history API 而不是网站内导航,以便以编程方式更改当前 URL。此类网站称为 SPA,是单页应用程序的缩写。
检测页面更改的常用 JS 方法
MutationObserver (docs) 从字面上检测 DOM 更改。
信息/示例:
轻量级观察器,仅在 URL 也更改时才对更改做出反应:
let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; onUrlChange(); } }).observe(document, {subtree: true, childList: true}); function onUrlChange() { console.log('URL changed!', location.href); }
通过发送 DOM 事件来发出内容更改信号的网站的事件侦听器:
pjax:end
被许多基于 pjax 的站点(例如 GitHub)使用,
请参阅如何在 pjax 加载之前和之后运行 jQuery?document
message
例如,在 Chrome 浏览器中使用 Google 搜索,
请参阅 Chrome 扩展程序检测 Google 搜索刷新window
yt-navigate-finish
由 Youtube 使用,
请参阅如何检测 YouTube 上的页面导航并无缝修改其外观?
通过 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(); });
P.S. 所有这些方法都可以在 WebExtension 的内容脚本中使用。这是因为我们正在查看的情况是通过 history.pushState 或 replaceState 更改 URL,因此页面本身在相同的内容脚本环境中保持不变。
评论