gpt4 book ai didi

javascript - 如何在运行脚本之前等待页面完成所有内容的加载或如何最好地检测主要的 DOM 更改

转载 作者:行者123 更新时间:2023-11-30 06:52:27 24 4
gpt4 key购买 nike

我正在使用 here 中描述的方法制作文本替换扩展名(某种)作为替换文本的基础。

下面是重要的代码

var elements = document.getElementsByTagName('*');

for (var i = 0; i < elements.length; i++) {
var element = elements[i];

for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];

if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace(/[word or phrase to replace here]/gi, '[new word or phrase]');

if (replacedText !== text) {
element.replaceChild(document.createTextNode(replacedText), node);
}
}
}
}

现在这在 99% 的情况下都可以正常工作,但在某些计算机上(我假设基于计算机的速度和它缓存的内容)此代码在某些网站上不起作用,最重要的是在谷歌搜索上。该脚本肯定会运行,但找不到任何可替换的东西。我最好的猜测是它在完成加载并将来自 google 的所有数据添加到 DOM 之前加载并运行脚本。

我有两个问题

1) 有什么方法可以检测到 google 在运行脚本之前已经完成了它需要做的事情吗?或者这本质上是不可能的,因为(我假设)发生了一些异步的事情。

2) 如果我无法检测到它完全完成加载,检测文本或图像元素已添加到 DOM(或在 DOM 上编辑)以便我可以重新运行函数的最佳方法是什么替换文本?

在此先感谢您的帮助。

最佳答案

假设您定义了一个 REPLACE 函数...

function REPLACE(text) {
console.log(text);
// change text here
return text;
}

首先,您应该使用 TreeWalker更有效地遍历 DOM。

function walk(root) {
var walker = document.createTreeWalker(root,
window.NodeFilter.SHOW_TEXT, null, false);

var node;
while ((node = walker.nextNode())) {
node.textContent = REPLACE(node.textContent);
}
}

对于动态 DOM,最好的选择是使用 MutationObserver API。

function initMO(root) {
var MO = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MO(function(mutations) {
observer.disconnect();
mutations.forEach(function(mutation){
var node = mutation.target;
if (node.nodeType === document.ELEMENT_NODE)
walk(node);
else
node.textContent = REPLACE(node.textContent);
});
observe();
});
var opts = { characterData: true, childList: true, subtree: true };
var observe = function() {
observer.takeRecords();
observer.observe(root, opts);
};
observe();
}

请记住,在调用观察者之前可能会收集多个突变记录,并且一些更改可能不再存在于实时 DOM 上。这是因为 MutationObserver 应该( browsers are buggy in some corner cases )仅在所有代码在当前堆栈/任务上完成后才作为微任务触发。

在进行可能触发更多记录的更改之前小心断开观察者,否则您将挂起您的浏览器/系统。

要完成解决方案:

document.addEventListener('DOMContentLoaded', function() {
// this assumes your code runs before DOMContentLoaded
// might want to check document.readyState
// or use jQuery's ready() instead
walk(document.documentElement);
initMO(document.documentElement);
});

打开这个fiddle看到它在行动。

注意:在 Firefox 中存在一个不一致的地方,即 childList 的变化是针对 textContent-only 的变化而触发的,所以请记住这一点。

您可能会找到 MutationSummary图书馆方便。查看promotional video

关于javascript - 如何在运行脚本之前等待页面完成所有内容的加载或如何最好地检测主要的 DOM 更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34603089/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com