仅动态包含javascript文件一次 [英] Dynamically including javascript files only once

查看:101
本文介绍了仅动态包含javascript文件一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆