删除元素后的 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 被移除并重新创建后,观察者停止工作。

第三个问题:

and appears again after a second

行为将完全取决于您的意思。

如果您的意思是创建具有相同 idnew 元素,那么是的,这是预期的行为:当您调用 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 你断开它。如果您没有对原始元素做任何事情,那么观察者除了占用内存之外什么也没有做。但是同样,如果您要删除该元素,您应该断开观察者。