9

这是JS代码:

var wrap = document.createElement("div");
wrap.innerHTML = '<script type="text/javascript" src="'+scriptUrl+'"></script>';
var wrapscript = wrap.childNodes[0];
document.body.appendChild(wrapscript)

正文确实插入了脚本元素,但是没有加载 JS 资源,甚至没有 http 请求。

有人可以解释为什么会这样吗?

问题在于 Zeptojs 的 $ 方法

$('<script type="text/javascript" src="'+scriptUrl+'"></script>').appendTo($("bdoy"))

它像上面的代码一样工作,并导致错误。

4

3 回答 3

24

这个是微不足道的。

如规范(8.4 解析 HTML 片段8.2.3.5 其他解析状态标志)中所述,引用:

使用innerHTML浏览器时会

  1. 创建一个新的 Document 节点,并将其标记为 HTML 文档。

  2. 如果存在上下文元素,且上下文元素的 Document 处于 quirks 模式,则让 Document 处于 quirks 模式。否则,如果存在上下文元素,并且上下文元素的 Document 处于 limited-quirks 模式,则让 Document 处于 limited-quirks 模式。否则,让文档处于无怪癖模式。

  3. 创建一个新的 HTML 解析器,并将其与刚刚创建的 Document 节点相关联。...

并且在解析<script>内部时

如果在创建解析器时为与解析器关联的文档启用了脚本,则脚本标志设置为“启用”,否则设置为“禁用”。

即使解析器最初是为 HTML 片段解析算法创建的,即使脚本元素在这种情况下不执行,也可以启用脚本标志。

所以它不会被执行,只要你用innerHTML.

并且 usinginnerHTML将阻止创建 <script>元素永久执行。

如规范(4.3.1 脚本元素,)中所述,引用:

动态更改 src、type、charset、async 和 defer 属性没有直接影响;这些属性仅在下面描述的特定时间使用。

总结下面的描述是,它只src在注入时解析属性<script>document不管是哪个,包括使用时创建的临时innerHTML属性。)

所以,只要你想给文档注入脚本并让它执行,你就必须使用script = document.createElement('script').

设置它的属性srctype,可能是里面的内容(通过使用script.appendChild(document.createTextNode(content))),然后将其附加到document.body.

于 2012-11-15T06:57:33.027 回答
4

你可以试试这个:

var wrap = document.createElement('div');
var scr = document.createElement('script');
scr.src = scriptUrl;
scr.type = 'text/javascript';
wrap.appendChild(scr);
document.body.appendChild(wrap);

通过显式创建脚本标记,您是在告诉 JS,innerHTML 不是文本,而是可执行脚本。

于 2012-11-15T02:41:10.330 回答
4

当您无法控制插入机制并且您被迫使用带有script信标的 innerHTML 时,一个可能的解决方案是从“幽灵”节点重建 DOM 节点。

这是广告技术行业中反复出现的问题,其中许多自动化系统复制任意 HTML 代码(也称为广告服务器 ^^)。

在 Chrome 中运行良好:

var s = wrap.getElementsByTagName('script');
for (var i = 0; i < s.length ; i++) {
  var node=s[i], parent=node.parentElement, d = document.createElement('script');
  d.async=node.async;
  d.src=node.src;
  parent.insertBefore(d,node);
  parent.removeChild(node);
}

(你可以在 JSFiddle 中测试它

于 2014-09-26T13:46:18.903 回答