脚本标签创建与div的innerHTML不起作用

时间:2012-11-15 02:12:18

标签: javascript

这里是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的$ method

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

它的工作方式与上面的代码类似,并导致错误

3 个答案:

答案 0 :(得分:19)

这个是微不足道的。

如规范(8.4 Parsing HTML fragments8.2.3.5 Other parsing state flags中所述),引用:

使用innerHTML时,浏览器将

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

  2.   
  3. 如果有上下文元素,并且上下文元素的Document处于怪癖模式,则让Document处于怪癖模式。   否则,如果有一个context元素,那么Doc​​ument   context元素处于有限怪异模式,然后让Document进入   有限怪癖模式。否则,请将文档置于无怪癖模式。

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

  6.   

以及解析内部的<script>

  

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

     

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

所以只要你用innerHTML注入它就不会被执行。

使用innerHTML会阻止永久执行 <script>元素。

如规范(4.3.1 The script element)中所述,引用:

  

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

总结下面描述的 ,它只会在src注入<script>时解析document属性(无论哪个,包括{ {3}}在使用innerHTML时创建。)

因此,只要您想要将脚本注入文档并使其执行,您就必须使用script = document.createElement('script')

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

答案 1 :(得分:3)

你可以试试这个:

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不是文本,而是可执行脚本。

答案 2 :(得分:2)

一种可能的解决方案,当你无法控制插入机制并且你被迫使用带有script信标的innerHTML时,就是从&#34; ghost&#34;重建DOM节点。的。

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

在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);
}

(你可以test it in JSFiddle