我尝试在<div>上使用innerHTML加载一些脚本到页面中。脚本似乎加载到DOM中,但它从未执行(至少在Firefox和Chrome中)。有一种方法让脚本执行时插入他们与innerHTML?

示例代码:

<!DOCTYPE html > < html > <身体onload = " . getelementbyid(机)。innerHTML = '<script>alert(\'hi\')<\/script>'"> 难道不应该出现“hi”的提醒吗? < div id = "装载机" > < / div > 身体< / > < / html >


当前回答

尝试使用template和document.importNode。这里有一个例子:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Sample</title> </head> <body> <h1 id="hello_world">Sample</h1> <script type="text/javascript"> var div = document.createElement("div"); var t = document.createElement('template'); t.innerHTML = "Check Console tab for javascript output: Hello world!!!<br/><script type='text/javascript' >console.log('Hello world!!!');<\/script>"; for (var i=0; i < t.content.childNodes.length; i++){ var node = document.importNode(t.content.childNodes[i], true); div.appendChild(node); } document.body.appendChild(div); </script> </body> </html>

其他回答

您必须使用eval()来执行作为DOM文本插入的任何脚本代码。

MooTools会自动为你做这件事,我相信jQuery也会(取决于版本)。jQuery 1.6+版本使用eval)。这节省了大量解析<script>标记和转义内容的麻烦,以及一堆其他“陷阱”。

通常情况下,如果你要自己eval()它,你想要创建/发送没有任何HTML标记的脚本代码,如<script>,因为这些将不能正确地eval()。

你可以这样做:

var mydiv = document.getElementById("mydiv");
var content = "<script>alert(\"hi\");<\/script>";

mydiv.innerHTML = content;
var scripts = mydiv.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
    eval(scripts[i].innerText);
}

下面是一个递归函数来设置一个元素的innerHTML,我在我们的广告服务器中使用:

// o: container to set the innerHTML
// html: html text to set.
// clear: if true, the container is cleared first (children removed)
function setHTML(o, html, clear) {
    if (clear) o.innerHTML = "";

    // Generate a parseable object with the html:
    var dv = document.createElement("div");
    dv.innerHTML = html;

    // Handle edge case where innerHTML contains no tags, just text:
    if (dv.children.length===0){ o.innerHTML = html; return; }

    for (var i = 0; i < dv.children.length; i++) {
        var c = dv.children[i];

        // n: new node with the same type as c
        var n = document.createElement(c.nodeName);

        // copy all attributes from c to n
        for (var j = 0; j < c.attributes.length; j++)
            n.setAttribute(c.attributes[j].nodeName, c.attributes[j].nodeValue);

        // If current node is a leaf, just copy the appropriate property (text or innerHTML)
        if (c.children.length == 0)
        {
            switch (c.nodeName)
            {
                case "SCRIPT":
                    if (c.text) n.text = c.text;
                    break;
                default:
                    if (c.innerHTML) n.innerHTML = c.innerHTML;
                    break;
            }
        }
        // If current node has sub nodes, call itself recursively:
        else setHTML(n, c.innerHTML, false);
        o.appendChild(n);
    }
}

你可以在这里看到演示。

Krasimir Tsonev有一个伟大的解决方案,可以克服所有的问题。 他的方法不需要使用eval,因此不存在性能和安全问题。 它允许你用js设置innerHTML字符串包含html,并立即将其转换为DOM元素,同时还执行代码中存在的js部分。简短,简单,完全按你想要的工作。

享受他的解决方案吧:

http://krasimirtsonev.com/blog/article/Convert-HTML-string-to-DOM-element

重要提示:

您需要用div标签包装目标元素 你需要用div标签包装src字符串。 如果你直接写src字符串,它包括js部分,请注意正确地写结束脚本标记(在/之前有\),因为这是一个字符串。

你也可以像这样包装你的<脚本>,它将被执行:

<your target node>.innerHTML = '<iframe srcdoc="<script>alert(top.document.title);</script>"></iframe>';

请注意:srcdoc中的作用域指向iframe,因此您必须像上面的示例一样使用top来访问父文档。