为什么通过DOMParser创建的脚本元素不会执行?

时间:2015-01-23 15:09:47

标签: javascript html dynamic-script-loading

我在Ajax中加载HTML,用DOMParser解析它并将文档正文的所有childNodes放入文档片段。

当我将片段添加到当前文档的正文中时,<script>标记不会被执行。

我摆弄并想出如果我用新动态创建的脚本标签替换它们,它们就会被正确执行。

我想知道为什么?

E.g。

var html = "Some html with a script <script>alert('test');</script>";

var frag = parsePartialHtml(html);


fixScriptsSoTheyAreExecuted(frag);


document.body.appendChild(frag);


function fixScriptsSoTheyAreExecuted(el) {
  var scripts = el.querySelectorAll('script'),
      script, fixedScript, i, len;

  for (i = 0, len = scripts.length; i < len; i++) {
    script = scripts[i];

    fixedScript = document.createElement('script');
    fixedScript.type = script.type;
    if (script.innerHTML) fixedScript.innerHTML = script.innerHTML;
    else fixedScript.src = script.src;
    fixedScript.async = false;

    script.parentNode.replaceChild(fixedScript, script);
  }
}


function parsePartialHtml(html) {
  var doc = new DOMParser().parseFromString(html, 'text/html'),
      frag = document.createDocumentFragment(),
      childNodes = doc.body.childNodes;

  while (childNodes.length) frag.appendChild(childNodes[0]);

  return frag;
}

不调用fixScriptsSoTheyAreExecuted,就不会执行任何操作。

我发现难以理解的另一点是,如果我尝试简单地克隆现有脚本节点以使用cloneNode创建新节点,则它不起作用,哪种类型表明脚本标记是最初由DOMParser携带状态创建,阻止它们被执行。

1 个答案:

答案 0 :(得分:14)

DOM Parsing and Serialization规范中解释了这一点:

  

<强> parseFromString

     

parseFromString(str, type)方法必须运行这些步骤,   取决于类型:

     
      
  • "text/html"

         

    使用HTML parser解析str,并返回新创建的document

         

    scripting flag必须设置为“已停用”。

         

    注意
      script元素标记为不可执行且内容为   noscript被解析为标记。

  •