仅动态包含javascript文件一次

时间:2009-12-10 02:49:58

标签: javascript jquery

我正在编写一个javascript函数,用于包含外部JS文件,但只有一次。我需要这样一个函数的原因是因为在通过AJAX加载某些内容时调用它并且我需要为该内容运行特定于页面的代码(不,只是使用.live不会覆盖它)。 / p>

这是我的尝试,为简洁而缩短:

$.include_once = function(filename) {
    if ($("script[src='" + filename + "']").length === 0) {
        var $node = $("<script></script>")
            .attr({
                src : filename,
                type : "text/javascript"
            })
        ;
        $(document.body).append($node);
    }
};

这很好用:调用函数,加载外部文件,加载时运行该文件。完美。

问题是它总是会重新加载那个外部文件:我用来检查脚本是否存在的查询总是找不到任何东西!

调试时,我添加了几行:

alert($("script").length);     // alerts: 4
$(document.body).append($node);
alert($("script").length);     // alerts: 4

查看动态源代码(Firebug的HTML选项卡),我根本找不到脚本标记。

我知道我可以维护一个我以前包含的文件数组,但是我希望使用这样的方法(如果有效),看起来有点健壮,因为不是所有的JS文件以这种方式包含在内。

任何人都可以解释在第二个代码段中看到的行为吗?

3 个答案:

答案 0 :(得分:5)

在这种情况下,jQuery有点愚蠢;它完全不符合你的期望。当append($node) jQuery执行此操作时:

jQuery.ajax({
  url: $node.src,
  async: false,
  dataType: "script"
})

Woops!对于本地文件(例如,在同一个域上),jQuery为.js文件正文执行标准XMLHttpRequest,并通过创建<script>标记的整个复杂过程继续“评估”它(再次! )并将内容设置为.js文件正文。这是为了模拟eval但在全局范围内。

对于跨域文件,由于相同域策略无法执行标准XMLHttpRequest,因此jQuery会再次创建<script>元素并将其插入<head>。< / p>

在上面的本地和跨域案例中,jQuery 终于开始执行此操作:

head.removeChild(script);

繁荣您的.length支票!长号。

关于你的问题,不要打扰jQuery。只是做

document.getElementsByTagName('head')[0]
  .appendChild(
    document.createElement('script')
  )
  .src = filename;

这会做你期望的事情,特别是稍后会查询它。

答案 1 :(得分:3)

您正在尝试解决已经多次解决的问题。例如,尝试LazyLoad。 jQuery也有类似的插件。

答案 2 :(得分:0)

不设置script-tag的source属性,而是设置script标签的“text”属性。这适用于所有现代浏览器(我在实践中使用的应用程序不支持IE6,因此我不知道这种蠕变......)。

在实践中它看起来像这样(你必须添加代码以省略自己的双重包含 - 例如所有alread加载脚本的简单数组,虽然这是非常特定于应用程序的,为什么你应该加载代码两次?尝试省略双重加载代码......!):

var script_source_code_string = <some dynamically loaded script source code>;
var $n = $("<script></script>");
$n.get(0).text = script_source_code_string;
$(document.body).append($n);

甚至更简单(没有jquery,我的代码在这个阶段不知道jquery,它也可能是动态加载的):

var script_source_code_string = <some dynamically loaded script source code>;
var s = document.createElement('script');
document.getElementsByTagName('head')[0].appendChild(s);
s.text = script_source_code_string;
相关问题