免责声明:我知道为什么我应该避免使用 document.write 和 document.write 清除页面。
假设我需要在 DOM 加载时 (document.readyState = 'loading'
) 注入一个
synchronous(阻塞)脚本,但就在另一个特定的现有同步脚本之前。
如果我可以访问 HTML 代码,我可以这样写:
<html>
<head>
<title>It's okay</title>
<script>
document.write(
'<script src="https://www.googletagmanager.com/gtm.js?id=GTM-WZNT8QT" onload="console.log(1)"><'+'/script>'
);
</script>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" onload="console.log(2)"></script>
</head>
<body>
<script>console.log('DOM is parsed')</script>
</body>
</html>
它正确地加载了两个 JS 文件,并输出
1
, 2
, DOM is parsed
到控制台。
现在,如果我尝试使用
MutationObserver
来做到这一点(即检测何时插入新脚本节点,但在实际调用脚本之前),
<html>
<head>
<title>Why not loading?</title>
<script>
// Say, this JS is invoked by the extension before even parsing HTML
new MutationObserver((mutationList) => {
for (const mutation of mutationList) {
for (const node of mutation.addedNodes) {
if (node.tagName !== 'SCRIPT' || !node.src.includes('jquery')) {
continue;
}
document.write(
'<script src="https://www.googletagmanager.com/gtm.js?id=GTM-WZNT8QT" onload="console.log(1)"><'+'/script>'
);
}
}
}).observe(document, { childList: true, subtree: true });
</script>
<script src="https://code.jquery.com/jquery-3.6.3.min.js" onload="console.log(2)"></script>
</head>
<body>
<script>console.log('Now DOM is parsed!')</script>
</body>
</html>
...它不仅使浏览器“始终加载”某些内容,而且永远不会将
2
和 Now DOM is parsed!
打印到控制台。检查实际的 HTML 代码后,头部只有“googletagmanager”脚本。 JavaScript 线程未被阻塞。实际上document.readyState
从那一刻起总是停留'loading'
,有效地卡住和破碎。
问题:
事实上,有了
MutationObserver
,我至少可以通过在突变处理程序中说jquery
来阻止node.setAttribute('src', 'text/prevented')
代码运行,所以在它之前或之后插入googletagmanager脚本并不重要。我试图理解为什么它不起作用。