我正在构建一个查找单词的 Chrome 扩展程序,如果该单词出现在网页上,它就会变得模糊。为此,我在网页上查找所有文本(节点类型 1)节点,并将它们替换为新节点。当我创建一个新节点并将要替换的节点的文本分配给它时出现问题,运行时此脚本给出错误“RangeError:超出最大调用堆栈大小”
当我将常量字符串分配给要创建的节点时,不会出现此问题。这个脚本运行良好。
var targetNode=document.body
var config = { attributes: true, childList: true, subtree: true };
var callback = function(mutationsList, observer) {
walk(document.body);
};
var observer = new MutationObserver(callback);
observer.observe(targetNode, config);
function walk(node)
{
var child, next;
switch ( node.nodeType )
{
case 1: // Element
case 9: // Document
case 11: // Document fragment
child = node.firstChild;
while ( child )
{
next = child.nextSibling;
walk(child);
child = next;
}
break;
case 3: // Text node
handleText(node);
break;
}
}
function handleText(textNode)
{
var str = textNode.nodeValue;
if (str == "Manchester"){
//console.log(str);
p=textNode.parentNode;
const modified = document.createElement('span');
modified.id="bblur";
modified.textContent = "Constant"; // this works
modified.style.filter="blur(5px)";
modified.addEventListener("mouseover", mouseOver, false);
modified.addEventListener("mouseout", mouseOut, false);
p.replaceChild(modified, textNode);
}
//textNode.nodeValue = str;
//textNode.style.filter="blur(5px)";
}
function mouseOver()
{
this.style.filter="blur(0px)";
}
function mouseOut()
{
this.style.filter="blur(5px)";
}
这个 handleText 函数不起作用
function handleText(textNode)
{
var str = textNode.nodeValue;
if (str == "Manchester"){
//console.log(str);
p=textNode.parentNode;
const modified = document.createElement('span');
modified.id="bblur";
modified.textContent = str; //this doesn't work :/
modified.style.filter="blur(5px)";
modified.addEventListener("mouseover", mouseOver, false);
modified.addEventListener("mouseout", mouseOut, false);
p.replaceChild(modified, textNode);
}
}
我不希望使用固定字符串创建新节点,但我希望新节点中包含旧节点的文本内容。我可以做些什么来避免这个调用堆栈限制达到问题。谢谢!
最佳答案
死循环是因为你在 MutationObserver 回调中修改了 DOM。它与 "Constant"
一起工作,因为您有条件 "if (str == "Manchester")"
可以防止 DOM 修改并且不会触发 MutationObserver 回调。尝试使用常量 "Manchester"
,您将再次看到无限循环。
最简单的解决方法是忽略您已经替换的节点:
function walk(node)
{
var child, next;
switch ( node.nodeType )
{
case 1: // Element
case 9: // Document
case 11: // Document fragment
child = node.firstChild;
while ( child )
{
next = child.nextSibling;
if (child.id !== 'bblur') {
walk(child);
}
child = next;
}
break;
case 3: // Text node
handleText(node);
break;
}
}
您的代码还将为所有替换元素分配相同的 ID。最好使用不同的方式来标记新节点,例如您可以使用 dataset
属性。
关于javascript - 当我通过 chrome 扩展的内容脚本修改网页中的单词时,超出了最大调用堆栈大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56555733/