简体   繁体   English

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

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

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.它像上面的代码一样工作,并导致错误。

This one was trivial.这是微不足道的。

As stated in spec ( 8.4 Parsing HTML fragments and 8.2.3.5 Other parsing state flags ,) quote:如规范( 8.4 解析 HTML 片段8.2.3.5 其他解析状态标志)中所述,引用:

when using innerHTML the browser will使用innerHTML ,浏览器将

  1. Create a new Document node, and mark it as being an HTML document.创建一个新的 Document 节点,并将其标记为 HTML 文档。

  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.如果存在上下文元素,并且上下文元素的 Document 处于 quirks 模式,则让 Document 处于 quirks 模式。 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.创建一个新的 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 innerHTML will 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;动态更改 src、type、charset、async 和 defer 属性没有直接影响; these attribute are only used at specific times described below.这些属性仅在下面描述的特定时间使用。

Concluding the described below is that, it only parse the src attribute when injecting the <script> to the document (no matter which, including the temporary one created when using innerHTML .)总结下面描述的是,它只在将<script>注入document时解析src属性(无论哪种,包括使用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 src and type , possibly the contents inside (by using script.appendChild(document.createTextNode(content)) ), then append it to the document.body .设置它的属性,如srctype ,可能是里面的内容(通过使用script.appendChild(document.createTextNode(content)) ),然后将其附加到document.body

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

A possible solution, when you don't have control over the insertion mechanism and you are forced to use innerHTML with script beacons, 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 中测试它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM