无法附加 <script> 元素

IT技术 javascript jquery
2021-02-05 00:31:30

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

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

好消息是:

它 100% 有效。

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

Karl Swedberg 对jQuery API 站点中访客的评论做了很好的解释希望重复自己的一切话,你可以直接读取出现在这里(我发现很难通过导航的评论那里)

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()来添加脚本。

SourceURLs ( blog.getfirebug.com/2009/08/11/... ) 可能有助于调试问题。
2021-03-10 00:31:30
谢谢。我认为您指的是第一次出现的“UnusedReferencedObjects”,它应该是您在加载的脚本中创建的任何对象。我想如果您看到 DeleteObject 函数的作用,您会更好地理解它,它只是删除您传递给该函数的任何对象。为了清楚起见,我会在代码中添加一些注释。:)
2021-03-27 00:31:30
很好的解释,谢谢!但是是“UnusedReferencedObjects”吗?
2021-03-31 00:31:30
超级帖子!aCrosman 的例子对我不起作用,在准备好你的帖子后,我替换了 $("#someElement").append(script); 与 $("#someElement")[0].appendChild(script); 哪个修复了它:)感谢解释
2021-04-05 00:31:30
$.getScript 内置于 jQuery 中。
2021-04-09 00:31:30

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

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

来自:jQuery 的 JSON

2021-03-17 00:31:30
<script> 标签需要添加到 DOM 本身,而不是添加到现有元素的 innerHTML。
2021-03-22 00:31:30
$("#someElement")[0].appendChild( script );
2021-03-31 00:31:30
如果您真的希望元素出现在 DOM 中,不要只使用 jQuery 的 append。使用本机 appendChild 来实现这一点。
2021-04-03 00:31:30
@Diodeus 的innerHTML 是DOM 的一部分,它由浏览器动态解析,所以这是一个有效的案例。
2021-04-08 00:31:30

可以使用jQuery 函数动态加载 JavaScript 文件getScript

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

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

这不会向 DOM 中插入任何内容。它调用eval().
2021-03-30 00:31:30

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

jQuery 检测到您正在尝试创建 SCRIPT 元素,并将自动在全局上下文中运行该元素的内容。你是说这对你不起作用?——

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

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

惊人的!似乎没有原生原生等价物,但没有绝望,因为您总是可以先加载 jQuery
2021-04-08 00:31:30

这有效:

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

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

James 的代码对我来说效果更好。不仅因为它既不需要$(), [0], 也不需要转义(例如\/script),还因为这里的代码出于某种原因不能处理多个标签(例如,多个脚本),而@James' 可以。
2021-03-25 00:31:30
这是在我的情况下唯一有效的解决方案。上面的其他 sol'ns 依赖于提前出现在 html 文件中的 javascript 代码。由于我是动态添加代码,这样的javascript代码无法提前知道!谢谢达尔文!!
2021-03-31 00:31:30