你知道为什么下面这段代码没有将脚本元素添加到DOM中吗?
var code = "<script></script>";
$("#someElement").append(code);
你知道为什么下面这段代码没有将脚本元素添加到DOM中吗?
var code = "<script></script>";
$("#someElement").append(code);
当前回答
这是我认为最好的解决办法。谷歌分析就是这样注入的。
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函数getScript动态加载JavaScript文件
$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() { Display.sharePrice(); });
现在外部脚本将被调用,如果不能加载它,它将优雅地降级。
这是我认为最好的解决办法。谷歌分析就是这样注入的。
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); })();
好消息是:
100%有效。
只需在脚本标记中添加一些内容,例如alert('voila!');。您可能想问的正确问题是,“为什么我在DOM中没有看到它?”
Karl Swedberg在jQuery API网站上对访问者的评论做了一个很好的解释。我不想重复他所有的话,你可以直接在这里阅读(我发现很难浏览那里的评论)。
All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM. I believe that one of the reasons jQuery does this is to avoid "Permission Denied" errors that can occur in Internet Explorer when inserting scripts under certain circumstances. It also avoids repeatedly inserting/evaluating the same script (which could potentially cause problems) if it is within a containing element that you are inserting and then moving around the DOM.
接下来,我将通过使用.append()函数添加一个脚本来总结坏消息。
坏消息是…
你不能调试代码。
我不是在开玩笑,即使你添加了调试器;关键字,你将最终只得到对象的调用堆栈,而看不到源代码上的断点,(更不用说这个关键字只适用于webkit浏览器,所有其他主流浏览器似乎都省略了这个关键字)。
如果您完全理解您的代码是做什么的,那么这将是一个小缺点。但如果你不这样做,你最终会添加一个调试器;关键字到处都是,只是为了找出你(或我)的代码有什么问题。不管怎样,还有另一种选择,不要忘记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()来添加脚本。
将脚本追加到正文:
$(document).ready(function() {
$("<script>", { src : "bootstrap.min.js", type : "text/javascript" }).appendTo("body");
});
如此:
$('body').append($("<script>alert('Hi!');<\/script>")[0]);
jQuery似乎在脚本上做了一些聪明的事情,所以你需要附加html元素而不是jQuery对象。