代码之家  ›  专栏  ›  技术社区  ›  nickf

仅动态包含一次javascript文件

  •  5
  • nickf  · 技术社区  · 14 年前

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

    以下是我的尝试,简称为简洁:

    $.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 回复  |  直到 12 年前
        1
  •  5
  •   Crescent Fresh nosklo    14 年前

    在这种情况下,jquery有点愚蠢;它根本不像您期望的那样。当你 append($node) jquery执行以下操作:

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

    哎呀!对于本地文件(如在同一域上),jquery执行标准 XMLHttpRequest 对于.js文件体,并通过创建 <script> 标签(再次!)设置它是 内容 到.js文件体。这是为了模拟 eval 但在全球范围内。

    对于跨域文件,因为它不能执行标准 对象 由于相同的域策略,jquery再次创建 <脚本& GT; 元素并将其插入 <head> .

    在jquery上面的本地和跨域案例中 最后 开始这样做:

    head.removeChild(script);
    

    繁荣 你的 .length 检查!真倒霉。

    所以对于您的问题,不要用这个来打扰jquery。只要做

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

    这将实现您所期望的,尤其是稍后对其进行WRT查询。

        2
  •  3
  •   Jordan Running    14 年前

    你试图解决一个已经解决了好几次的问题。尝试 LazyLoad 例如。jquery也有类似的插件。

        3
  •  0
  •   Frunsi    14 年前

    不要设置脚本标记的源属性,而是设置脚本标记的“文本”属性。这完全有效 现代的 浏览器(我在实践中使用的应用程序不支持IE6,所以我不知道这个爬行…)。

    在实践中,它看起来是这样的(您必须添加代码来省略自己的双重包含——例如,一个简单的数组,包含所有已加载的脚本,尽管这是非常具体的应用程序,为什么还要加载两次代码呢?尝试忽略双重加载代码…!):

    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;