删除元素后的 MutationObserver 行为
MutationObserver behavior after the element was removed
我有一个 MutationObserver
绑定到 #foo
html 元素。
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// ...
});
});
当用户点击 #button
元素时,#foo
被删除并在一秒钟后再次出现。
<div id="button">Click me to remove the Foo!</div>
<div id="foo">Hello, I'm Foo!</div>
正如我所注意到的,在 #foo
被移除并重新创建后,观察者停止工作。
- 这是正常行为吗?
- 那么,我需要再次启动观察器吗?
第三个问题:
- 第一个观察者是否被完全移除?或者,不是那样,它仍然是 运行ning,只有 "doing nothing"? - 我在问这个问题,因为我不想要多个观察者 运行,如果只有其中一个观察者在做真正的工作。
and appears again after a second
行为将完全取决于您的意思。
如果您的意思是创建具有相同 id
的 new 元素,那么是的,这是预期的行为:当您调用 observer.observe
元素,您是在 那个特定元素 上调用它,而不是任何与其 ID 匹配的元素。如果您从 DOM 中删除该元素并将其替换为另一个看起来相同的不同元素,则观察者不会神奇地连接到该新的不同元素:
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
console.log("#foo was modified");
});
observer.observe(target, {subTree: true, childList: true});
var counter = 0;
tick();
setTimeout(function() {
console.log("Replacing foo with a new one");
target.parentNode.removeChild(target);
target = document.createElement("div");
target.id = "foo";
target.innerHTML = "This is the new foo";
document.body.insertBefore(target, document.body.firstChild);
}, 1000);
function tick() {
target.appendChild(document.createTextNode("."));
if (++counter < 20) {
setTimeout(tick, 200);
}
}
<div id="foo">This is the original foo</div>
如果您的意思是您将 相同的元素 放回 DOM,那么不,这不是预期的行为,而不是发生在这个例子:
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
console.log("#foo was modified");
});
observer.observe(target, {subTree: true, childList: true});
var counter = 0;
tick();
setTimeout(function() {
console.log("Removing foo for a moment");
target.parentNode.removeChild(target);
setTimeout(function() {
console.log("Putting the same foo back in");
document.body.insertBefore(target, document.body.firstChild);
}, 100);
}, 1000);
function tick() {
target.appendChild(document.createTextNode("."));
if (++counter < 20) {
setTimeout(tick, 200);
}
}
<div id="foo">This is the original foo</div>
这里的关键信息是观察者正在观察你传递给 observe
的 一个特定元素 。
这些问题仅在您删除旧元素并将其替换为全新元素时适用:
So, I need to launch the observer again?
如果您要删除原始元素并放置一个新元素,您应该告诉观察者停止观察:
observer.disconnect();
有了新元素后,您可以将观察者连接到它:
observer.observe(theNewElement, /*...options go here...*/);
Is the first observer is totally removed? Or, instead of that, it is still running, with just "doing nothing"?
在理论中,由于the spec明确指出它是对其观察者有引用的元素,那么如果你释放对该元素的唯一引用,理论上,观察者断开连接是因为元素及其观察者列表被清理了。但是,尚不清楚观察者的 disconnect
方法在观察者没有返回元素的引用的情况下如何实现,因此它们可能具有相互引用。如果您保留对观察者的引用,那将在内存中保留相互引用。可以肯定的是,我会故意断开它。
I'm asking about it, because I don't want the multiple observers run, if only one of them doing the real work.
观察者不会“运行”,他们会做出反应。观察者会继续观察原来的元素until/unless 你断开它。如果您没有对原始元素做任何事情,那么观察者除了占用内存之外什么也没有做。但是同样,如果您要删除该元素,您应该断开观察者。
我有一个 MutationObserver
绑定到 #foo
html 元素。
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// ...
});
});
当用户点击 #button
元素时,#foo
被删除并在一秒钟后再次出现。
<div id="button">Click me to remove the Foo!</div>
<div id="foo">Hello, I'm Foo!</div>
正如我所注意到的,在 #foo
被移除并重新创建后,观察者停止工作。
- 这是正常行为吗?
- 那么,我需要再次启动观察器吗?
第三个问题:
- 第一个观察者是否被完全移除?或者,不是那样,它仍然是 运行ning,只有 "doing nothing"? - 我在问这个问题,因为我不想要多个观察者 运行,如果只有其中一个观察者在做真正的工作。
and appears again after a second
行为将完全取决于您的意思。
如果您的意思是创建具有相同 id
的 new 元素,那么是的,这是预期的行为:当您调用 observer.observe
元素,您是在 那个特定元素 上调用它,而不是任何与其 ID 匹配的元素。如果您从 DOM 中删除该元素并将其替换为另一个看起来相同的不同元素,则观察者不会神奇地连接到该新的不同元素:
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
console.log("#foo was modified");
});
observer.observe(target, {subTree: true, childList: true});
var counter = 0;
tick();
setTimeout(function() {
console.log("Replacing foo with a new one");
target.parentNode.removeChild(target);
target = document.createElement("div");
target.id = "foo";
target.innerHTML = "This is the new foo";
document.body.insertBefore(target, document.body.firstChild);
}, 1000);
function tick() {
target.appendChild(document.createTextNode("."));
if (++counter < 20) {
setTimeout(tick, 200);
}
}
<div id="foo">This is the original foo</div>
如果您的意思是您将 相同的元素 放回 DOM,那么不,这不是预期的行为,而不是发生在这个例子:
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
console.log("#foo was modified");
});
observer.observe(target, {subTree: true, childList: true});
var counter = 0;
tick();
setTimeout(function() {
console.log("Removing foo for a moment");
target.parentNode.removeChild(target);
setTimeout(function() {
console.log("Putting the same foo back in");
document.body.insertBefore(target, document.body.firstChild);
}, 100);
}, 1000);
function tick() {
target.appendChild(document.createTextNode("."));
if (++counter < 20) {
setTimeout(tick, 200);
}
}
<div id="foo">This is the original foo</div>
这里的关键信息是观察者正在观察你传递给 observe
的 一个特定元素 。
这些问题仅在您删除旧元素并将其替换为全新元素时适用:
So, I need to launch the observer again?
如果您要删除原始元素并放置一个新元素,您应该告诉观察者停止观察:
observer.disconnect();
有了新元素后,您可以将观察者连接到它:
observer.observe(theNewElement, /*...options go here...*/);
Is the first observer is totally removed? Or, instead of that, it is still running, with just "doing nothing"?
在理论中,由于the spec明确指出它是对其观察者有引用的元素,那么如果你释放对该元素的唯一引用,理论上,观察者断开连接是因为元素及其观察者列表被清理了。但是,尚不清楚观察者的 disconnect
方法在观察者没有返回元素的引用的情况下如何实现,因此它们可能具有相互引用。如果您保留对观察者的引用,那将在内存中保留相互引用。可以肯定的是,我会故意断开它。
I'm asking about it, because I don't want the multiple observers run, if only one of them doing the real work.
观察者不会“运行”,他们会做出反应。观察者会继续观察原来的元素until/unless 你断开它。如果您没有对原始元素做任何事情,那么观察者除了占用内存之外什么也没有做。但是同样,如果您要删除该元素,您应该断开观察者。