我在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
携带状态创建,阻止它们被执行。
答案 0 :(得分:14)
DOM Parsing and Serialization规范中解释了这一点:
<强>
parseFromString
强>
parseFromString(str, type)
方法必须运行这些步骤, 取决于类型:
"text/html"
使用
HTML parser
解析str
,并返回新创建的document。scripting flag必须设置为“已停用”。