Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

simple MutationObserver version of DOMNodeRemovedFromDocument

Tags:

javascript

dom

I attach some functionality to DOM elements and want to be able to clear all references when the element is removed from the DOM so it can be garbage collected,

My initial version to detect the removel of an element was this:

var onremove = function(element, callback) {
    var destroy = function() {
        callback();
        element.removeEventListener('DOMNodeRemovedFromDocument', destroy);
     };
     element.addEventListener('DOMNodeRemovedFromDocument', destroy);
};

Then I read that mutation events were deprecated in favor of MutationObserver. So I tried to port my code. This is what I came up with:

 var isDescendant = function(desc, root) {
     return !!desc && (desc === root || isDecendant(desc.parentNode, root));
 };

var onremove = function(element, callback) {
    var observer = new MutationObserver(function(mutations) {
        _.forEach(mutations, function(mutation) {
            _.forEach(mutation.removedNodes, function(removed) {
                if (isDescendant(element, removed)) {
                    callback();

                    // allow garbage collection
                    observer.disconnect();
                    observer = undefined;
                }
            });
        });
    });
    observer.observe(document, {
         childList: true,
         subtree: true
    });
};

This looks overly complicated to me (and not very efficient). Am I missing something or is this really the way this is supposed to work?

like image 349
tobib Avatar asked Aug 04 '15 00:08

tobib


People also ask

What is window MutationObserver?

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.

What is a MutationObserver?

MutationObserver is a built-in object that observes a DOM element and fires a callback when it detects a change. We'll first take a look at the syntax, and then explore a real-world use case, to see where such thing may be useful.

How do I use MutationObserver in JavaScript?

Here's the code: let options = { characterData: true }, observer = new MutationObserver(mCallback); function mCallback(mutations) { for (let mutation of mutations) { if (mutation. type === 'characterData') { // Do something here... } } } Notice again the type being looked for in the callback function is characterData .

How do you observe DOM changes?

One way to watch for DOM changes in our JavaScript web app is to use the MutationObserver constructor. })(); to create the MutationObserver instance with a loop to append child elements to the body within the async function. We insert a new p element after 1 second 5 times.


1 Answers

Actually... yes, there is a more elegant solution :).

What you added looks good and seems to be well optimized. However there is an easier way to know if the node is attached to the DOM or not.

function onRemove(element, onDetachCallback) {
    const observer = new MutationObserver(function () {
        function isDetached(el) {
            if (el.parentNode === document) {
                return false;
            } else if (el.parentNode === null) {
                return true;
            } else {
                return isDetached(el.parentNode);
            }
        }

        if (isDetached(element)) {
            observer.disconnect();
            onDetachCallback();
        }
    })

    observer.observe(document, {
         childList: true,
         subtree: true
    });
}
like image 170
robert Avatar answered Oct 12 '22 21:10

robert