从本质上讲,我希望在DIV的内容发生变化时执行脚本。由于脚本是分开的(Chrome扩展和网页脚本中的内容脚本),我需要一种简单地观察DOM状态变化的方法。我可以设置民意调查,但这看起来很草率。
Edit
这个答案现在已弃用。请看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
//...
});
这个示例监听文档及其整个子树上的DOM更改,它将在元素属性更改以及结构更改时触发。规范草案有一个完整的有效突变侦听器属性列表:
childList Set to true if mutations to target's children are to be observed. attributes Set to true if mutations to target's attributes are to be observed. characterData Set to true if mutations to target's data are to be observed. subtree Set to true if mutations to not just target, but also target's descendants are to be observed. attributeOldValue Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded. characterDataOldValue Set to true if characterData is set to true and target's data before the mutation needs to be recorded. attributeFilter Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed.
(此列表截至2014年4月;如有任何更改,请查阅说明书。)
除了MutationObserver API提供的“原始”工具外,还有一些“方便”库可以处理DOM突变。
考虑:MutationObserver以子树的形式表示每个DOM更改。例如,如果你在等待某个元素被插入,它可能在mutations.mutation[i]. adddednodes [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 (docs) to literally detect DOM changes. Info/examples: How to change the HTML content as it's loading on the page Performance of MutationObserver to detect nodes in entire DOM. Lightweight observer to react to a change only if URL also changed: 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); } Event listener for sites that signal content change by sending a DOM event: pjax:end on document used by many pjax-based sites e.g. GitHub, see How to run jQuery before and after a pjax load? message on window used by e.g. Google search in Chrome browser, see Chrome extension detect Google search refresh yt-navigate-finish used by Youtube, see How to detect page navigation on YouTube and modify its appearance seamlessly? Periodic checking of DOM via setInterval: Obviously this will work only in cases when you wait for a specific element identified by its id/selector to appear, and it won't let you universally detect new dynamically added content unless you invent some kind of fingerprinting the existing contents. Cloaking History API: let _pushState = History.prototype.pushState; History.prototype.pushState = function (state, title, url) { _pushState.call(this, state, title, url); console.log('URL changed', url) }; Listening to hashchange, popstate 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,这样页面本身在相同的内容脚本环境中保持不变。
推荐文章
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- HTML5文本区域占位符不出现
- 添加javascript选项选择
- 在Node.js中克隆对象
- 我如何捕捉Ajax查询后错误?
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- jQuery:什么是限制“数字”仅输入文本框的最佳方法?(允许使用小数点)
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?