获取已添加DOM节点的className(MutationObserver)

10
我正在编写一个简单的用户脚本,如果Facebook帖子包含某些特定词语,它将自动隐藏该帖子。核心功能已经实现,但我的MutationObserver似乎无法正确读取mutation.addedNodes的className。我循环遍历mutation.addedNodes并检查其中是否有class为userContentWrapper的元素,但测试结果始终为false,即使该元素确实有这个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);
};

我只能假设观察者在节点完全形成之前分析了该节点,并且还没有设置所有属性。我该如何让观察者等待,直到节点完全形成才处理它?或者是我没有理解问题吗?
提前感谢您的帮助...
1个回答

12

其中一些添加的节点是容器,因此您应该检查它们的内部:

const observer = new MutationObserver(onMutation);
observer.observe(document, {
  childList: true,
  subtree: true,
});

function onMutation(mutations) {
  const found = [];
  for (const { addedNodes } of mutations) {
    for (const node of addedNodes) {
      if (!node.tagName) continue; // not an element
      if (node.classList.contains('userContentWrapper')) {
        found.push(node);
      } else if (node.firstElementChild) {
        found.push(...node.getElementsByClassName('userContentWrapper'));
      }
    }
  }
  found.forEach(processFilter);
}

MutationObserver回调函数被执行为微任务,会阻止DOM和JS引擎,因此尽量使其快速执行,特别是在运行复杂站点(如生成大量DOM变化的Facebook)时。可以在开发者工具(F12键)的分析器/时间线面板中进行测试。


childListsubtree添加到观察参数中不会自动深入挖掘吗? - Cliff
它不会扩展添加的内容。例如,someNode.appendChild(anotherNodeWith1000children)不会被扩展,因为它只是一个操作。 - wOxxOm
哦,我以为这就是childList的工作方式,然后subtree会自动搜索所有后代。那么subtree实际上在做什么呢? - Cliff
正如文档所述:subtree报告后代的变化。一个变化可能包括通过insertAdjacentHTML或其他方式添加或删除多个节点。而childList使观察者关注这种活动。如果没有它,在这些情况下回调函数将不会被执行。 - wOxxOm
这里有一个多余的括号。 - user3685048
谢谢!这节省了我很多麻烦。需要注意的一点是,在else if中,应该使用node.getElementsByClassName()而不是node.getElementsByTagName()吧? - tklives

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接