在head中加载的脚本无法向body注入元素的解决方案咨询
解决head中脚本无法向body注入元素的问题
问题根源:你放在head里的自执行脚本会在浏览器解析到<body>标签前就运行,此时document.getElementsByTagName('body')[0]返回null,直接触发了if(target == null){return};语句,导致创建和注入元素的代码根本没机会执行。
以下是几种可行的解决办法:
办法1:监听DOMContentLoaded事件
等浏览器完成DOM解析后再执行注入逻辑,此时body元素已经存在。修改代码如下:
<head> (function() { // 等待DOM加载完成 document.addEventListener('DOMContentLoaded', function() { const target = document.getElementsByTagName('body')[0]; var myScript = document.createElement('script'); myScript.setAttribute('type', 'text/plain'); myScript.setAttribute('data-cookiecategory', 'analytics'); myScript.innerHTML = 'window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag("js",new Date());gtag("config","id");'; if(target != null){ target.prepend(myScript); } }); })(); </head>
办法2:用MutationObserver监听body元素的创建
如果需要在body刚被添加到DOM时就注入(比DOMContentLoaded更早),可以用MutationObserver监听document的变化:
<head> (function() { // 先检查body是否已存在 let target = document.getElementsByTagName('body')[0]; if(target) { injectScript(target); return; } // 监听document的子节点变化 const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { const body = document.getElementsByTagName('body')[0]; if(body) { injectScript(body); observer.disconnect(); // 完成后停止监听 } }); }); observer.observe(document, { childList: true, subtree: true }); // 提取注入逻辑为复用函数 function injectScript(target) { var myScript = document.createElement('script'); myScript.setAttribute('type', 'text/plain'); myScript.setAttribute('data-cookiecategory', 'analytics'); myScript.innerHTML = 'window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag("js",new Date());gtag("config","id");'; target.prepend(myScript); } })(); </head>
办法3:手动创建body(不推荐)
如果页面还没有body元素(极端情况),可以手动创建并添加到document,但可能干扰页面正常结构,仅在必要时使用:
<head> (function() { let target = document.getElementsByTagName('body')[0]; if(!target) { // 手动创建body元素并添加到文档根节点 target = document.createElement('body'); document.documentElement.appendChild(target); } var myScript = document.createElement('script'); myScript.setAttribute('type', 'text/plain'); myScript.setAttribute('data-cookiecategory', 'analytics'); myScript.innerHTML = 'window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag("js",new Date());gtag("config","id");'; target.prepend(myScript); })(); </head>
内容的提问来源于stack exchange,提问作者Sandro Antonucci
相关产品推荐
相关产品推荐

