不能附加<script>元素

任何想法为什么下面的代码片段不添加到DOM的脚本元素?

var code = "<script></script>"; $("#someElement").append(code); 

我发现有些浏览器在直接执行这些更改时并不尊重某些更改(我的意思是从文本中创buildHTML,就像使用脚本标记一样),但是当使用内置命令执行这些更改时事情变好了。 尝试这个:

 var script = document.createElement( 'script' ); script.type = 'text/javascript'; script.src = url; $("#someElement").append( script ); 

来自: JSON的jQuery

好消息是:

这是100%的工作。

只需在脚本标签内添加一些内容,如alert('voila!'); 。 你可能想问的正确的问题可能是“我为什么没有在DOM中看到它?”

Karl Swedberg在jQuery API网站上对访问者的评论做了一个很好的解释。 我不想重复他所有的话,你可以这里直接阅读(我发现很难浏览那里的评论)

所有jQuery的插入方法在内部使用一个domManip函数在插入到DOM之前和之后清理/处理元素。 domManip函数所做的一件事就是提取所有要插入的脚本元素,并通过“evalScript例程”运行它们,而不是将其注入DOM片段的其余部分。 它分别插入脚本,评估它们,然后从DOM中删除它们。

我相信,jQuery这样做的原因之一是避免在某些情况下插入脚本时,Internet Explorer中可能发生的“权限被拒绝”错误。 它还避免了重复插入/评估相同的脚本(这可能会导致问题),如果它位于要插入的包含元素中,然后围绕DOM移动。

接下来,我将通过使用.append()函数来添加脚本来总结坏消息。


而坏消息是..

你不能debugging你的代码。

即使添加了debugger; ,我也不是在开玩笑, 关键字在你想要设置为断点的行之间,你最终只会得到对象的调用堆栈,而不会在源代码中看到断点(更不用说这个关键字只在webkit浏览器中工作,其他所有的主要浏览器似乎省略了这个关键字)

如果你完全理解你的代码的作用,那么这将是一个小缺陷。 但是,如果你不这样做,你最终会添加一个debugger; 关键字到处都是为了找出你的(或我的)代码有什么问题。 无论如何,还有一个select,不要忘了,JavaScript可以本地操纵HTML DOM。


解决方法。

使用JavaScript(而不是jQuery)来操作HTML DOM

如果你不想失去debugging能力,那么你可以使用javascript原生的HTML DOM操作。 考虑这个例子:

 var script = document.createElement("script"); script.type = "text/javascript"; script.src = "path/to/your/javascript.js"; // use this for linked script script.text = "alert('voila!');" // use this for inline script document.body.appendChild(script); 

在那里,就像过去的日子不一样。 不要忘了清理东西,无论是在DOM中还是在内存中,所有被引用的对象都不再需要,以防止内存泄漏。 你可以考虑这个代码来清理:

 document.body.removechild(document.body.lastChild); delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load. 

从这个解决方法的缺点是,您可能会无意中添加重复的脚本,这是不好的。 从这里你可以稍微模仿.append()函数,在添加之前添加一个对象validation,并在添加之后从DOM中删除脚本。 考虑这个例子:

 function AddScript(url, object){ if (object != null){ // add script var script = document.createElement("script"); script.type = "text/javascript"; script.src = "path/to/your/javascript.js"; document.body.appendChild(script); // remove from the dom document.body.removeChild(document.body.lastChild); return true; } else { return false; }; }; function DeleteObject(UnusedReferencedObjects) { delete UnusedReferencedObjects; } 

这样,您可以添加具有debuggingfunction的脚本,同时避免脚本重复。 这只是一个原型,你可以扩展任何你想要的。 我一直在使用这个方法,对此非常满意。 果然,我永远不会使用jQuery .append()来添加一个脚本。

快乐的编码,
亨德拉Uzia。

可以使用jQuery函数getScriptdynamic加载JavaScript文件

 $ .getScript('http://www.whatever.com/shareprice/shareprice.js',function(){
   Display.sharePrice();
 });

现在外部脚本将被调用,如果不能被加载,它将会优雅地降级。

你是什​​么意思“不工作”?

jQuery检测到你正在尝试创build一个SCRIPT元素,并会自动在全局上下文中运行该元素的内容。 你是否告诉我这不适合你? –

 $('#someElement').append('<script>alert("WORKING");</script>'); 

编辑:如果在运行命令之后没有看到DOM中的SCRIPT元素(例如在Firebug中),就像我说的那样,将运行代码,然后删除SCRIPT元素 – 我相信SCRIPT元素总是附加到身体…但无论如何 – 放置在这种情况下绝对不影响代码执行。

这工作:

 $('body').append($("<script>alert('Hi!');<\/script>")[0]); 

看起来好像jQuery正在做一些聪明的脚本,所以你需要添加html元素而不是jQuery对象。

试试这可能是有帮助的:

 var fileref=document.createElement('script'); fileref.setAttribute("type","text/javascript"); fileref.setAttribute("src","scriptAnalytics.js"); document.getElementsByTagName("head")[0].appendChild(fileref); 

我想要做同样的事情,但要在其他框架中追加脚本标记!

 var url = 'library.js'; var script = window.parent.frames[1].document.createElement('script' ); script.type = 'text/javascript'; script.src = url; $('head',window.parent.frames[1].document).append(script); 
 <script> ... ...jQuery("<script></script>")... ... </script> 

string文字中的</script>终止整个脚本,以避免可以使用"</scr" + "ipt>"

在脚本文件中添加sourceURL有助于在此页面中提到: https : //blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

  1. 在脚本文件中,添加一个sourceURL语句,如“// @ sourceURL = foo.js”
  2. 使用jQuery $ .getScript()加载脚本,脚本将在chrome dev工具的“sources”选项卡中可用

你的脚本正在执行,你不能使用它的document.write 。 使用警报来testing它并避免使用document.write 。 你的js文件和document.write语句不会被执行,其余的函数将被执行。

这是我认为是最好的解决scheme。 Google Analytics(分析)就是这样注入的。

 var (function(){ var p="https:" == document.location.protocol ? "https://" : "http://"; d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.src=p+'url-to-your-script.js'; s.parentNode.insertBefore(g,s); })(); 

你不需要jQuery来创build一个Script DOM元素 。 这可以用香草ES6来完成,就像这样:

 const script = "console.log('Did it work?')" new Promise((resolve, reject) => { (function(i,s,o,g,r,a,m){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.innerText=g;a.onload=r;m.parentNode.insertBefore(a,m)})(window,document,'script',script, resolve()) }).then(() => console.log('Sure did!')) 

它不需要被包装在一个Promise ,但是这样做可以让你在脚本加载时解决承诺,帮助防止长时间运行的脚本的竞争条件。

将脚本附加到正文:

 $(document).ready(function() { $("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body"); }); 

另一种方法,你可以做到这一点,如果你想追加代码是使用document.createElement方法,但使用.innerHTML而不是.src

 var script = document.createElement( 'script' ); script.type = 'text/javascript'; script.innerHTML = 'alert("Hey there... you just appended this script to the body");'; $("body").append( script ); 

我试过这个,工作正常。 用\x3Creplace<符号。

 // With Variable var code = "\x3Cscript>SomeCode\x3C/script>"; $("#someElement").append(code); 

要么

 //Without Variable $("#someElement").append("\x3Cscript>SomeCode\x3C/script>"); 

你可以在这里testing代码。

只需通过jQueryparsing来创build一个元素。

 <div id="someElement"></div> <script> var code = "<script>alert(123);<\/script>"; $("#someElement").append($(code)); </script> 

工作示例: https : //plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz