无法附加<script>元素</script>

时间:2009-03-04 15:11:47

标签: javascript jquery

知道为什么下面这段代码没有将脚本元素添加到DOM?

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

18 个答案:

答案 0 :(得分:347)

好消息是:

100%正常工作。

只需在脚本代码中添加内容,例如alert('voila!');。您可能想问的正确问题, “我为什么不在DOM中看到它?”

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

  

所有jQuery的插入方法都使用   内部的domManip函数   在和之前清理/处理元素   将它们插入DOM后。   domManip的其中一件事   函数确实是拉出任何脚本   即将插入和运行的元素   他们通过“evalScript例程”   而不是注入其余的   DOM片段。它插入了   脚本分开,评估它们,   然后将它们从DOM中删除。

     

我相信jQuery的原因之一   这是为了避免“许可   否认“可能发生的错误   插入时的Internet Explorer   在某些情况下的脚本。   它也反复避免   插入/评估相同的脚本   (这可能会导致   问题)如果它在一个包含内   要插入的元素和   然后移动DOM。

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


而坏消息是......

您无法调试代码。

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

如果你完全理解你的代码所做的事情,那么这将是一个小缺点。但是如果你不这样做,你最终会在整个地方添加debugger;关键字,以找出你(或我的)代码的错误。无论如何,有一个替代方案,不要忘记javascript本身可以操纵HTML DOM。


解决方法。

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

如果您不想失去调试功能,那么您可以使用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()函数,并在添加后立即从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;
}

这样,您可以添加具有调试功能的脚本,同时避免脚本双重性。这只是一个原型,您可以根据自己的需要进行扩展。我一直在使用这种方法并对此非常满意。果然我永远不会使用jQuery .append()添加脚本。

答案 1 :(得分:253)

我已经看到一些问题,某些浏览器在你直接执行这些更改时不尊重某些更改(我的意思是通过文本创建HTML,就像你尝试使用脚本标记一样),但是当你使用内置标签创建它们时-in命令事情变得更好。试试这个:

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

来自:JSON for jQuery

答案 2 :(得分:23)

可以使用jQuery function getScript

动态加载JavaScript文件
$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
  Display.sharePrice();
});

现在将调用外部脚本,如果无法加载,它将正常降级。

答案 3 :(得分:20)

你的意思是“不工作”?

jQuery检测到您正在尝试创建SCRIPT元素,并将自动在全局上下文中运行元素的内容。你告诉我这不适合你吗? -

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

编辑:如果在运行命令后没有在DOM中看到SCRIPT元素(例如在Firebug中),因为jQuery,就像我说的那样,将运行代码,然后将删除SCRIPT元素 - 我相信SCRIPT元素总是附加到正文......但无论如何 - 在这种情况下,放置对代码执行完全没有影响。

答案 4 :(得分:17)

这有效:

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

似乎jQuery正在使用脚本做一些聪明的事情,所以你需要附加html元素而不是jQuery对象。

答案 5 :(得分:14)

尝试这可能会有所帮助:

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

答案 6 :(得分:3)

<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

字符串文字中的</script>会终止整个脚本,以避免使用"</scr" + "ipt>"代替。

答案 7 :(得分:3)

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

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

答案 8 :(得分:2)

如本页所述,在脚本文件中添加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”选项卡中提供

答案 9 :(得分:1)

您的脚本正在执行,您无法使用document.write。使用警报对其进行测试,避免使用document.write。使用document.write的js文件的语句将不会被执行,其余的函数将被执行。

答案 10 :(得分:1)

这是我认为最好的解决方案。 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); })();

答案 11 :(得分:1)

您不需要jQuery来创建Script DOM Element。它可以像香草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中,但这样做可以让您在脚本加载时解析承诺,从而有助于防止长时间运行脚本的竞争条件。

答案 12 :(得分:0)

将脚本附加到正文:

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

答案 13 :(得分:0)

如果要添加代码,另一种方法是使用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 );

答案 14 :(得分:0)

我试过这个one并且运行正常。只需将<符号替换为\x3C即可。

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


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

您可以测试代码here

答案 15 :(得分:0)

可以尝试这样

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

你不能做"<script></script>"的唯一原因是因为javascript中不允许使用字符串,因为DOM层无法解析js和HTML的内容。

答案 16 :(得分:0)

我写了一个npm包,可让您使用HTML字符串包括脚本标记,并在执行脚本

时将其附加到容器中>

示例:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

在此处找到它:https://www.npmjs.com/package/appendhtml

答案 17 :(得分:-1)

只需使用jQuery解析它就可以创建一个元素。

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

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