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

示例代码:

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


当前回答

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

享受他的解决方案吧:

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

重要提示:

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

其他回答

我使用了这个代码,它工作得很好

var arr = MyDiv.getElementsByTagName('script')
for (var n = 0; n < arr.length; n++)
    eval(arr[n].innerHTML)//run script inside div

我有这个问题与innerHTML,我不得不追加一个Hotjar脚本的“头部”标签我的Reactjs应用程序,它将必须立即执行追加后。

将动态节点导入“head”标签的一个很好的解决方案是React-helment模块。


此外,对于所提出的问题,还有一个有用的解决方案:

在innerHTML中没有脚本标记!

事实证明,HTML5不允许使用innerHTML属性动态添加脚本标记。因此,下面的代码将不会执行,也不会出现Hello World!

element.innerHTML = "<script>alert('Hello World!')</script>";

这在HTML5规范中有记录:

注意:使用innerHTML插入的脚本元素不执行时 它们是插入的。

但是要注意,这并不意味着innerHTML不受跨站点脚本的影响。可以通过innerHTML执行JavaScript,而不使用MDN的innerHTML页面上所示的标记。

解决方案:动态添加脚本

要动态添加脚本标记,您需要创建一个新的脚本元素并将其附加到目标元素。

你可以为外部脚本这样做:

var newScript = document.createElement("script");
newScript.src = "http://www.example.com/my-script.js";
target.appendChild(newScript);

和内联脚本:

var newScript = document.createElement("script");
var inlineScript = document.createTextNode("alert('Hello World!');");
newScript.appendChild(inlineScript); 
target.appendChild(newScript);

我自己的扭曲,使用现代JS和typescript。不知道为什么人们过滤tagName等时,querySelector就在那里。

对我来说很有魅力:

function makeScriptsExecutable(el: Element) {
  el.querySelectorAll("script").forEach(script => {
    const clone = document.createElement("script")

    for (const attr of script.attributes) {
      clone.setAttribute(attr.name, attr.value)
    }

    clone.text = script.innerHTML
    script.parentNode?.replaceChild(clone, script)
  })
}

这里有一个非常有趣的解决方案: http://24ways.org/2005/have-your-dom-and-script-it-too

所以使用this代替script标签:

<img src="empty.gif" onload="alert('test');this. parentnode . removechild (this);"/>

下面是一个更现代(和简洁)的mmm解决方案:

function executeScriptElements(containerElement) {
  const scriptElements = containerElement.querySelectorAll("script");

  Array.from(scriptElements).forEach((scriptElement) => {
    const clonedElement = document.createElement("script");

    Array.from(scriptElement.attributes).forEach((attribute) => {
      clonedElement.setAttribute(attribute.name, attribute.value);
    });
    
    clonedElement.text = scriptElement.text;

    scriptElement.parentNode.replaceChild(clonedElement, scriptElement);
  });
}

注意:我还尝试过使用cloneNode()或outerHTML的替代解决方案,但没有成功。