使用 div 的innerHTML 创建的脚本标记不起作用

IT技术 javascript html
2021-02-04 11:21:25

这是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"))

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

3个回答

这是微不足道的。

如规范(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.

并且使用innerHTML将阻止创建 <script>元素被永久执行。

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

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

结论性的以下说明的是,其仅解析src注入时的属性<script>document(无论哪个,包括临时一个使用时创建innerHTML)。

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

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

你可以试试这个:

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

呵呵,我知道。如果你用 document.createElement('script') 创建脚本标签,它就可以工作。用 innerHTML 创建就是 Zepto 的 $ 方法实现它的方式
2021-03-16 11:21:25

当您无法控制插入机制并且被迫使用带有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 中测试它

当然,如果textContent使用,d.setAttribute('type','text/javascript')还需要确保文本内容被评估为 javascript。
2021-03-18 11:21:25
如果脚本标签直接包含 javascript,那么您需要分配该textContent字段而不是(或除了)该src字段。在任何情况下,对于实际的实际解决方案,+1 适用于在客户端使用 javascript 的情况下,在预先存在的 HTML 模板上调用 document.createElement 是不可行的。
2021-04-01 11:21:25