我想插入一些javascript代码,


这应该在&lt中的其他javascript代码之前运行; body>
run。
当他们操纵< body>
中的html时,它们在里面< body>
。
通常我会把这个javascript放在< script&gt ;
标记在打开< body>
标记之后。但我不是直接写html。它是由一个程序为我生成的。 ( react-storybook )。它的API允许在< head>
中注入html,但不能注入< body>
。
< HEAD>
 <脚本>< /脚本> < - 我可以在这里注入一个脚本标签
< / head>
< body>
 <脚本>< /脚本> < - 我无法直接添加此脚本标记,但我需要一个

 < script>其他js< / script>
< / body>

&#xA;&#xA; 我尝试将我的js放入<代码>文档 加载
事件处理程序,但它们在body完全加载后运行,因此其他js已经运行。
我试过把我的js直接放在头部然后我的js不能在body上使用 appendChild
,因为那时 document.body
是null。
有没有办法插入满足上述两个要求的脚本标签,只能访问&lt; head&gt;
?
答案 0 :(得分:4)
我没有看到任何方法可以做到这一点,而不会破坏你尝试在其中工作并做一些相当讨厌的事情的工具。我怀疑这是解决潜在问题的更好方法。
我尝试将js直接放在头部,然后我的js无法在
appendChild
上使用body
,因为此时document.body
为空...
讨厌,可能是一个坏主意,但你可以强迫身体开始:
document.write("<body>");
此时,解析器将创建body
元素。然后,您可以使用appendChild
(或继续使用邪恶的document.write
)。当身体在正常过程中再次启动时,第二个开启标记将被忽略。
不是一个好主意。 react-storybook是开源的。如果没有办法实现你的实际目标,我建议修改它,这样你就可以而不是像上面那样做。
以下是一个示例,在Chrome,Firefox,IE11,IE8和iOS Safari中进行了测试和使用。
(Live copy on JSBin):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Example</title>
<script>
(function() {
var d = document.createElement("div");
d.innerHTML =
"This is the element appended to the body element " +
"that we forced to be created using the evil " +
"<code>document.write</code>";
document.write("<body>");
document.body.appendChild(d);
})();
</script>
</head>
<body>
<div>
This is the first element inside the body element in the markup.
</div>
</body>
</html>
答案 1 :(得分:2)
我尝试将js直接放在头部,然后我的js不能在身体上使用
appendChild
,因为此时document.body
为空。
MutationObserver救援!
您只需等待解析<body>
标记:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script>
new MutationObserver(function(records, self)
{
for(var i = 0; i < records.length; ++i)
{
for(var j = 0; j < records[i].addedNodes.length; ++j)
{
if(records[i].addedNodes[j].nodeName == 'BODY')
{
self.disconnect();
console.log('herp');
/*
At this point, the body exists, but nothing inside it has been parsed yet.
document.body might be available, but to be safe, you can use:
var body = records[i].addedNodes[j];
*/
}
}
}
}).observe(document.documentElement,
{
childList: true,
});
</script>
</head>
<body>
<script>console.log('derp');</script>
</body>
</html>
将其保存为HTML文件,在浏览器中打开,您应该在控制台中看到这一点(表示&#34; herp&#34;部分在&#34; derp&#34;之前运行;注意:如果在页面加载后打开控制台,Firefox似乎会丢弃消息顺序,但是&#34; herp&#34;部分实际上仍然在&#34; derp&#34; one)之前运行:)
herp
derp
(注意:以上代码不会作为堆栈代码工作,因为所有代码都放在<body>
标记中。)
现在只是为了安全起见,我会添加一项检查以查看是否已设置document.body
,并且只有在不是这样的情况下才设置MutationObserver:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script>
function onBodyLoaded(body)
{
console.log('herp');
/* Do whatever you want with "body" here. */
}
if(document.body)
{
onBodyLoaded(document.body)
}
else
{
new MutationObserver(function(records, self)
{
for(var i = 0; i < records.length; ++i)
{
for(var j = 0; j < records[i].addedNodes.length; ++j)
{
if(records[i].addedNodes[j].nodeName == 'BODY')
{
self.disconnect();
onBodyLoaded(records[i].addedNodes[j]);
}
}
}
}).observe(document.documentElement,
{
childList: true,
});
}
</script>
</head>
<body>
<script>console.log('derp');</script>
</body>
</html>
这样您可能根本不需要在您的身体上添加<script>
标记,只需将您想要在onBodyLoaded
函数中运行的代码放在其中。
如果您确实需要添加脚本标记,则可以使用:
function onBodyLoaded(body)
{
body.appendChild(document.createElement('script')).src = 'https://example.com/my.js';
}
或
function onBodyLoaded(body)
{
body.appendChild(document.createElement('script')).innerHTML = 'document.write("hi there")';
}
请注意,IE 10及更早版本不支持MutationObserver
。 IE 11和这个十年的任何其他浏览器应该可以工作。