I have a MutationObserver
binded to a #foo
html element.
var target = document.querySelector("#foo");
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
// ...
});
});
When user clicks #button
element, the #foo
is removed and appears again after a second.
<div id="button">Click me to remove the Foo!</div>
<div id="foo">Hello, I'm Foo!</div>
And as I noticed, after the #foo
was removed and recreated, the observer stopped working.
And the third quesion:
disconnect() The MutationObserver method disconnect() tells the observer to stop watching for mutations. The observer can be reused by calling its observe() method again.
Good answer! Yes, it's finally slower by just 10% or even less in recent versions of Chrome. @Bergi, it's for the case when processing is complex and takes a lot of time. MutationObserver runs in a microtask queue so multiple callbacks may still reside in one task, which can lead to very long paint frames and jank.
The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature, which was part of the DOM3 Events specification.
MutationObserver is a Web API provided by modern browsers for detecting changes in the DOM. With this API one can listen to newly added or removed nodes, attribute changes or changes in the text content of text nodes.
and appears again after a second
The behavior will depend entirely on what you mean by that.
If you mean a new element with the same id
is created, then yes, this is expected behavior: When you call observer.observe
on an element, you're calling it on that specific element, not any element matching its ID. If you remove that element from the DOM and replace it with another, different element that looks the same, the observer is not magically hooked up to that new, different element:
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>
If you mean you're putting the same element back in the DOM, then no, that wouldn't be expected behavior, and not what happens in this example:
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>
The key take-away message here is that the observer is observing the one specific element you pass into observe
.
These questions only apply if you're removing the old element and replacing it with a whole new one:
So, I need to launch the observer again?
If you're removing the original element and putting a new one in its place, you should tell the observer to stop observing:
observer.disconnect();
Once you have a new element, you can connect the observer to it:
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"?
In theory, since the spec makes it clear that it's the element that has a reference to its observers, then if you release your only reference to the element, in theory the observer gets disconnected because the element and its list of observers gets cleaned up. However, it's unclear how the observer's disconnect
method can be implemented without the observer having a reference back to the element, so they may have mutual references. If you keep your reference to the observer, that would keep the mutual references in memory. I'd disconnect it on purpose, to be sure.
I'm asking about it, because I don't want the multiple observers run, if only one of them doing the real work.
Observers don't "run," they react. The observer will continue observing the original element until/unless you disconnect it. If you're not doing anything to the original element, the observer isn't doing anything other than taking up memory. But again, if you're going to remove the element, you should disconnect the observer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With