我正在编写一个简单的用户脚本,如果它包含某个单词列表,它将自动隐藏Facebook帖子。核心功能有效,但我的MutationObserver
似乎无法正确阅读className
mutation.addedNodes
。我遍历mutation.addedNodes
并检查这些元素是否具有类userContentWrapper
,但该测试的结果始终为false - 即使该元素具有该类。
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);
};
我只能假设观察者正在分析添加的节点,然后才能完全形成所有属性。如何使观察者等待处理节点直到它完全完成?或者我不明白这个问题?
提前致谢...
答案 0 :(得分:5)
一些添加的节点是容器,因此您应该深入挖掘:
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回调作为一个阻止DOM和JS引擎的微任务执行,所以它应该非常快,尤其是在像facebook这样的复杂网站上,它会产生大量的DOM突变。
这可以在devtools( F12 key)分析器/时间线面板中进行测试。
如果您希望尽量减少使用MutationObserver的不利影响,请将大批量的更改推迟到下一个事件任务中:
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});
};