getting the className of added DOM node (mutationObserver)

主宰稳场 提交于 2019-12-21 05:45:26

问题


I'm writing a simple userscript that will auto-hide a Facebook post if it contains a certain list of words. The core functionality works, but my MutationObserver doesn't seem to read the className of mutation.addedNodes properly. I loop through mutation.addedNodes and check if any of those elements have the class userContentWrapper, but the result of that test is always false -- even if the element does have the class.

var startObserver = function() {        
    var observer = new MutationObserver(function(mutations) {        
        mutations.forEach(function(mutation) {            
            var added = mutation.addedNodes;            
            for (var i = 0; i < added.length; i++) {                
                if (/\buserContentWrapper\b/.test(added[i].className)) {
                    processFilter(added[i]);
                }
            }
        });        
    });    
    var obj = {childList: true, subtree: true, attributes: true};
    observer.observe(document.documentElement, obj);
};

I can only assume that the observer is analyzing the added node before it's fully formed with all the attributes in place. How can I make the observer wait to process the node until it's fully complete? Or am I not understanding the problem?

Thanks in advance...


回答1:


Some of the added nodes are containers, so you should dig deeper:

var startObserver = function() {
    var observer = new MutationObserver(function(mutations) {
        for (var m=0; m < mutations.length; m++) {
            var added = mutations[m].addedNodes;
            for (var i = 0; i < added.length; i++) {
                var node = added[i];
                if (node.nodeType != 1) { // not Node.ELEMENT_NODE
                    continue;
                }
                if (/\buserContentWrapper\b/.test(node.className)) {
                    processFilter(node);
                } else if (node.children.length) {
                    var nodes = node.getElementsByTagName('userContentWrapper');
                    for (var j = 0; j < nodes.length; j++) {
                        processFilter(nodes[j]);
                    }
                }
            }
        }
    });
    observer.observe(document, {childList: true, subtree: true});
};

MutationObserver callback is executed as a microtask that blocks DOM and JS engine, so it should be extremely fast, especially on a complex site such as facebook, which generates lots of DOM mutations.

This can be tested in devtools (F12 key) profiler/timeline panels.

If you want to minimize adverse effects of using a MutationObserver, postpone large batches of changes into next event task:

var startObserver = function() {
    new MutationObserver(function handler(mutations, observer, postponed) {
        if (mutations.length > 100 && postponed !== true) {
            setTimeout(handler, 0, mutations, observer, true);
            return;
        }
        for (var m=0; m < mutations.length; m++) {
            var added = mutations[m].addedNodes;
            for (var i = 0; i < added.length; i++) {
                var node = added[i];
                if (node.nodeType != 1) { // not Node.ELEMENT_NODE
                    continue;
                }
                if (node.classList.contains('userContentWrapper')) {
                    processFilter(node);
                } else if (node.children[0]) {
                    var nodes = node.getElementsByClassName('userContentWrapper');
                    for (var j = 0; j < nodes.length; j++) {
                        processFilter(nodes[j]);
                    }
                }
            }
        }
    }).observe(document, {childList: true, subtree: true});
};


来源:https://stackoverflow.com/questions/37979897/getting-the-classname-of-added-dom-node-mutationobserver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!