基本上我想在DIV的内容发生变化时执行脚本.由于脚本是独立的(chrome扩展和网页脚本中的内容脚本),我需要一种方法来简单地观察DOM状态的变化.我可以设置投票,但这似乎很草率.
是否有可能在DOM节点上观察到尚不存在的突变?
例:
我的应用程序在某些时候创建了一个div : <div id="message" data-message-content="foo" data-message-type="bar" />.
我想留意这个div的创造和变化.
var mutationObserver = new MutationObserver(function(mutations){
// Some code to handle the mutation.
});
mutationObserver.observe(
document.querySelector('#message'),
{
attributes: true,
subtree: true,
childList: true,
characterData: false
}
);
);
Run Code Online (Sandbox Code Playgroud)
现在这会返回一个错误,因为它#message是null(尚未创建div).
Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.
一个明显的解决方案是观察body和检查是否有任何突变div#Message,但这似乎是一个坏主意/或可能不利于性能.
我需要隐藏html页面中的一个部分:
<h1 data-ng-show="!menuPinned && !isSaaS" class="logo floatLeft" aria-hidden="false"><span>XXX </span><span style="font-weight: bold;">XXX </span><span>XXXXX</span></h1>
Run Code Online (Sandbox Code Playgroud)
以下代码在Chrome dev中正常运行.工具
var ibmlogo = document.querySelectorAll('h1.logo.floatLeft');
ibmlogo[1].remove();
Run Code Online (Sandbox Code Playgroud)
但是当我在脚本处于活动状态时加载页面时,部分(h1)将不会消失.我相信这是因为当脚本运行时,DOM尚未完成加载,因此脚本无法找到选择器.
我尝试了很多不同的东西(例如window.onLoad),但我的脚本仍然无效.最后一次尝试(失败)如下:
var logo = document.querySelectorAll('h1.logo.floatLeft');
logo.onload = function() {removeLogo()};
function removeLogo(){
console.log("### logo array lenght: " + logo.length);
logo[1].remove();
};
Run Code Online (Sandbox Code Playgroud)
有什么建议?谢谢Giovanni
我在我们的网站上进行A/B测试,我做的大部分工作都是在一个JS文件中,在文件顶部加载之前,其他任何东西都被渲染,但是在jQuery加载之后,它有时会派上用场.
举一个非常简单的改变H1标签的例子,我通常会在头部注入一个样式来将H1不透明度设置为0,然后在DOMContentLoaded上,我会操纵H1内容,然后将不透明度设置为1.是为了避免在更改发生之前闪现旧内容 - 隐藏整个对象在眼睛上更优雅.
我已经开始研究MutationObserver API了.我之前在使用覆盖对话框中更改内容时使用过这个用户可以打开的内容,这似乎是一个非常酷的方法,我想知道是否有人设法使用MutationObserver来收听文件,因为它是第一次加载/在首次渲染之前和DOMContentLoaded之前解析并更改文档?
这种方法可以让我更改H1内容而不必隐藏它,更改它,然后显示它.
到目前为止,我已经尝试但失败了,刚刚结束了关于即将到来的突变事件的阅读,并想知道我是否正在尝试做一些不可能的事情.然而,我们(不是我)已经设法将机器人放在火星上,所以我希望我能解决这个问题.
因此,可以使用MutationObservers在加载/解析页面时动态更改HTML内容吗?
感谢您的帮助或任何指示.
问候,尼克
javascript ab-testing optimizely mutation-observers mutation-events
鉴于此示例代码:
function someMethod(elements) {
var observer = new MutationObserver(function(events) {
SomeLib.each(events, function(event, k, i) {
if ( event.removedNodes ) {
SomeLib.each(event.removedNodes, function(removedElement, k, i) {
console.log(222, removedElement)
});
}
});
});
SomeLib.each(elements, function(element, k, i) {
console.log(111, element)
observer.observe(element, {
childList : true,
subtree : false
});
});
}
Run Code Online (Sandbox Code Playgroud)
我注意到如果我打电话someMethod(parentElement)然后稍后再打电话someMethod(parentElement.querySelector('someChildElement'))
第一个是唯一触发事件的调用,并且看起来好像第二个调用没有触发任何事件。
不幸的是,因为我最感兴趣的是实际节点被删除时的事件。没有其他的。子节点实际上也不感兴趣,但是选项childList必须data...如此true,所以我猜我是被迫的。
我无法围绕跟踪谁的父级已被跟踪或未被跟踪来组织我的代码,因此我会发现简单地侦听任何特定节点上的删除事件要容易得多,无论它最终以何种方式删除。
考虑到这种困境,我正在考虑MutationObserver在document元素上注册 a ,而是依赖于检测我希望通过自己的事件处理程序观察自己的元素。
但这真的是我最好的选择吗?
性能显然是值得关注的,因为一切都会触发这个文档监听器,但也许只有一个MutationObserver潜在的高效,因为我只会在检测到感兴趣的元素时触发我自己的函数。
然而,它可能需要在removedNodes和addedNodes上进行迭代,因此它对所有事物都有真正的影响,而不仅仅是我观察节点。
这就引出了一个问题,是否已经注册了一个全局突变观察者?
我真的需要自己手动观察文档吗?
如果其他库也开始在主体元素或子元素上观察类似的情况怎么办?
我不会破坏他们的实施吗?(并不是说我只是有依赖性)但这令人担忧这个实现实际上看起来是多么可怕 …
我发现 MutationObserver 文档相当混乱。我想观察文档主体何时将具有该类的 DIV 元素superelement添加到 DOM。
<div class="superelement" style="display:none;2"></div>
Run Code Online (Sandbox Code Playgroud)
我已经设法将这段代码粘合在一起:
const observer = new MutationObserver(onMutation);
observer.observe(document, {
childList: true,
subtree: true,
});
function onMutation(mutations) {
const found = [];
for (const { addedNodes } of mutations) {
for (const node of addedNodes) {
if (!node.tagName) {
continue; // not an element
} else {
if (node.classList.contains('superelement')) {
console.log(node)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
是否没有更干净的方法来迭代所有添加的元素?我可以想象这相当慢。
我正在尝试获取一种能够等待元素已经存在于 DOM 中的方法。我读过一些关于 的文章MutationObserver,并且我得到了这个方法,它应该可以完成我所需要的:
const waitForElement = async (queryString) => {
return new Promise((resolve) => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const nodes = Array.from(mutation.addedNodes);
nodes.forEach((node) => {
console.log('NODE CUSTOM', node);
if (node.matches && node.matches(queryString)) {
observer.disconnect();
resolve(node);
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
});
};
Run Code Online (Sandbox Code Playgroud)
然后,我可以这样简单地使用它:
await waitForElement('#id-of-element');
Run Code Online (Sandbox Code Playgroud)
问题是它实际上没有按预期工作:console.log仅记录“父母”元素,如果要搜索的元素位于树的深处,则似乎不会记录它(这正在更复杂的应用程序中使用) ,所以它可能与异步调用等有关)。
然而,我发现,我只需要查看实际元素是否在 DOM 中,而不是遍历突变和节点数组,所以我实现了这个:
const waitForElement = async (queryString) => { …Run Code Online (Sandbox Code Playgroud) javascript asynchronous document-ready mutation-observers queryselector
javascript ×7
dom ×2
html ×2
ab-testing ×1
asynchronous ×1
jquery ×1
optimizely ×1
tampermonkey ×1
web ×1