仅动态包含javascript文件一次 [英] Dynamically including javascript files only once
问题描述
我正在编写一个javascript函数,用于包含外部JS文件,但只有一次。我需要这样一个函数的原因是因为在通过AJAX加载某些内容时调用它并且我需要为该内容运行特定于页面的代码(不,只需使用 .live
不会覆盖它。)
I have a javascript function I'm writing which is being used to include an external JS file, but only once. The reason I need such a function is because it is being called when some content is loaded via AJAX and I need to run page-specific code to that content (no, just using .live
won't cover it).
这是我的尝试,为简洁而缩短:
Here's my attempt, shortened for brevity:
$.include_once = function(filename) {
if ($("script[src='" + filename + "']").length === 0) {
var $node = $("<script></script>")
.attr({
src : filename,
type : "text/javascript"
})
;
$(document.body).append($node);
}
};
这很好用:调用函数,加载外部文件,正在运行该文件加载时完美。
This works fine: the function is called, it loads the external file, and that file is being run when loaded. Perfect.
问题是它总会重新加载该外部文件:我用来检查脚本是否存在的查询总是找不到任何东西!
The problem is that it will always re-load that external file: the query I'm using to check for the presence of the script always finds nothing!
调试时,我添加了一些行:
When debugging this, I added some lines:
alert($("script").length); // alerts: 4
$(document.body).append($node);
alert($("script").length); // alerts: 4
查看动态源代码(Firebug的HTML标签页),我可以'找到脚本标签。
Looking in the dynamic source (the HTML tab of Firebug), I can't find the script tag at all.
我知道我可以维护一系列我以前包含的文件,但是我希望能用这样的方法因此,(如果它有效),似乎更健壮,因为不是所有的JS文件都以这种方式包含。
I know that I could maintain an array of files that I've previously included, but I was hoping to go with a method such as this, which (if it worked), seems a bit more robust, since not all the JS files are being included in this way.
任何人都可以解释在第二个片段中看到的行为?
推荐答案
在这种情况下,jQuery有点愚蠢;它完全不符合你的期望。当你追加($ node)
jQuery这样做:
jQuery is a bit of a dumb-dumb in this case; it doesn't do at all what you'd expect. When you append($node)
jQuery does this:
jQuery.ajax({
url: $node.src,
async: false,
dataType: "script"
})
Woops!对于本地文件(例如,在同一个域上),jQuery为.js文件正文执行标准的 XMLHttpRequest
,并通过创建一个完整的复杂过程来eval它。 < script>
标记(再次!)并将内容设置为.js文件正文。这是为了模拟 eval
但是在全局上下文中。
Woops! For local files (eg on the same domain) jQuery performs a standard XMLHttpRequest
for the .js file body, and proceeds to "eval" it by a whole convoluted process of creating a <script>
tag (again!) and settings it's contents to your .js file body. This is to simulate eval
but in the global context.
对于跨域文件,因为它无法执行标准 XMLHttpRequest
由于同域策略,jQuery再次创建< script>
元素并将其插入< head>
。
For cross-domain files, since it cannot perform the standard XMLHttpRequest
due to the same-domain policy, jQuery once again creates a <script>
element and inserts it into <head>
.
在jQuery 上面的本地和跨域案例中> em>绕过这样做:
In both the local and cross-domain cases above jQuery finally gets around to doing this:
head.removeChild(script);
booms 你的 .length
检查! Bummer。
And booms your .length
check! Bummer.
所以关于你的问题,不要打扰jQuery。只需执行
So on to your problem, don't bother jQuery with this. Just do
document.getElementsByTagName('head')[0]
.appendChild(
document.createElement('script')
)
.src = filename;
这会做你所期望的,尤其是稍后查询它。
Which will do what you'd expect, particularly wrt querying for it later.
这篇关于仅动态包含javascript文件一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!