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

示例代码:

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


当前回答

是的,你可以,但你必须在DOM之外做,而且顺序必须是正确的。

var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
window.onload = function(){
    var n = document.createElement("div");
    n.innerHTML = scr;
    document.body.appendChild(n);
}

...将提醒'foo'。这行不通:

document.getElementById("myDiv").innerHTML = scr;

即使这样也不行,因为先插入节点:

var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
window.onload = function(){
    var n = document.createElement("div");
    document.body.appendChild(n);
    n.innerHTML = scr;  
}

其他回答

是的,你可以,但你必须在DOM之外做,而且顺序必须是正确的。

var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
window.onload = function(){
    var n = document.createElement("div");
    n.innerHTML = scr;
    document.body.appendChild(n);
}

...将提醒'foo'。这行不通:

document.getElementById("myDiv").innerHTML = scr;

即使这样也不行,因为先插入节点:

var scr = '<scr'+'ipt>alert("foo")</scr'+'ipt>';
window.onload = function(){
    var n = document.createElement("div");
    document.body.appendChild(n);
    n.innerHTML = scr;  
}

单线解决方案如下:

document.getElementsByTagName("head")[0].append(document.createRange().createContextualFragment('<script src="https://google.com/file.js"></script>'));

尝试使用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,与脚本、链接脚本以及模块一起工作。

该函数接受3个参数:

要插入的html代码的字符串 Dest:目标元素的引用 Append:在目标元素HTML的末尾启用追加的布尔标志

function insertHTML(html, dest, append=false){
    // if no append is requested, clear the target element
    if(!append) dest.innerHTML = '';
    // create a temporary container and insert provided HTML code
    let container = document.createElement('div');
    container.innerHTML = html;
    // cache a reference to all the scripts in the container
    let scripts = container.querySelectorAll('script');
    // get all child elements and clone them in the target element
    let nodes = container.childNodes;
    for( let i=0; i< nodes.length; i++) dest.appendChild( nodes[i].cloneNode(true) );
    // force the found scripts to execute...
    for( let i=0; i< scripts.length; i++){
        let script = document.createElement('script');
        script.type = scripts[i].type || 'text/javascript';
        if( scripts[i].hasAttribute('src') ) script.src = scripts[i].src;
        script.innerHTML = scripts[i].innerHTML;
        document.head.appendChild(script);
        document.head.removeChild(script);
    }
    // done!
    return true;
}

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

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

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