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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13390588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:37:21  来源:igfitidea点击:

script tag create with innerHTML of a div doesn't work

javascripthtml

提问by Maxingchi

Here is the JS code:

这是JS代码:

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

The body did insert the script element, but the JS resource wasn't loaded, there isn't even an http request.

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

Could someone explain why this is happening?

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

The problem is with Zeptojs's $ method

问题出在 Zeptojs 的 $ 方法上

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

It works like the code above, and causes the bug.

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

回答by xiaoyi

This one was trivial.

这是微不足道的。

As stated in spec (8.4 Parsing HTML fragmentsand 8.2.3.5 Other parsing state flags,) quote:

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

when using innerHTMLthe browser will

使用innerHTML浏览器时会

  1. Create a new Document node, and mark it as being an HTML document.

  2. If there is a context element, and the Document of the context element is in quirks mode, then let the Document be in quirks mode. Otherwise, if there is a context element, and the Document of the context element is in limited-quirks mode, then let the Document be in limited-quirks mode. Otherwise, leave the Document in no-quirks mode.

  3. Create a new HTML parser, and associate it with the just created Document node. ...

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

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

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

and when parsing a <script>inside

并且在解析<script>内部时

The scripting flag is set to "enabled" if scripting was enabled for the Document with which the parser is associated when the parser was created, and "disabled" otherwise.

The scripting flag can be enabled even when the parser was originally created for the HTML fragment parsing algorithm, even though script elements don't execute in that case.

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

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

So it won't be executed, as long as you inject it with innerHTML.

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

And using innerHTMLwill prevent the<script>element created from being executed permanently.

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

As stated in spec (4.3.1 The script element,) quote:

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

Changing the src, type, charset, async, and defer attributes dynamically has no direct effect; these attribute are only used at specific times described below.

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

Concluding the described belowis that, it only parse the srcattribute when injecting the <script>to the document(no matter which, including the temporary onecreated when using innerHTML.)

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

So, as long as you want to inject a script to the document and make it executed, you have to use script = document.createElement('script').

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

Set its attributes like srcand type, possibly the contents inside (by using script.appendChild(document.createTextNode(content))), then append it to the document.body.

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

回答by inhan

You can try this instead:

你可以试试这个:

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

By creating the script tag explicitly you're telling JS that the innerHTML is not a text but instead it's an executable script.

通过显式创建脚本标签,你告诉 JS,innerHTML 不是文本,而是一个可执行脚本。

回答by Samuel_fr_29

A possible solution, when you don't have control over the insertion mechanism and you are forced to use innerHTML with scriptbeacons, is to rebuild DOM Nodes from the "ghost" ones.

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

This is a recurring problem in the ad-tech industry, in a which many automated systems duplicate arbitrary HTML code (aka. adservers ^^).

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

works fine in Chrome:

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

(you can test it in JSFiddle)

(你可以在 JSFiddle 中测试它