在<head>中从javascript添加<body>节点

时间:2016-06-25 11:04:10

标签: javascript html

我想插入一些javascript代码,

&#xA;&#xA;
    &#xA;
  1. 这应该在&lt中的其他javascript代码之前运行; body&gt; run。

  2. &#xA;
  3. 当他们操纵&lt; body&gt; 中的html时,它们在里面&lt; body&gt;

  4. &#xA;
&#xA;&#xA;

通常我会把这个javascript放在&lt; script&gt ; 标记在打开&lt; body&gt; 标记之后。但我不是直接写html。它是由一个程序为我生成的。 ( react-storybook )。它的API允许在&lt; head&gt; 中注入html,但不能注入&lt; body&gt;

&#xA;&#xA;
  &LT; HEAD&GT;&#XA; &LT;脚本&GT;&LT; /脚本&GT; &lt;  - 我可以在这里注入一个脚本标签&#xA;&lt; / head&gt;&#xA;&lt; body&gt;&#xA; &LT;脚本&GT;&LT; /脚本&GT; &lt;  - 我无法直接添加此脚本标记,但我需要一个&#xA;&#xA; &lt; script&gt;其他js&lt; / script&gt;&#xA;&lt; / body&gt;&#xA;  
&#xA;&#xA;

我尝试将我的js放入<代码>文档 加载事件处理程序,但它们在body完全加载后运行,因此其他js已经运行。

&#xA;&#xA;

我试过把我的js直接放在头部然后我的js不能在body上使用 appendChild ,因为那时 document.body 是null。

&#xA; &#xA;

有没有办法插入满足上述两个要求的脚本标签,只能访问&lt; head&gt;

&#xA;

2 个答案:

答案 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和这个十年的任何其他浏览器应该可以工作。