加载第二个版本的jQuery,以及其他库

时间:2012-09-29 16:59:18

标签: javascript jquery-ui jquery google-ajax-libraries

我正在创建一个小部件,其中包含一段代码,可以放入您的网站,然后通过js提取内容。这是一个示例代码段:

<div data-token="bc1cea6304e8" id="my-widget">
    <script src="http://localhost:8080/assets/eg-widget.js" type="text/javascript"></script>
</div>

我正在做一个测试来检查页面是否已经有jQuery,如果是,那么该版本至少为1.5。

if (typeof jQuery == 'undefined' || isVersion("1.5", ">")) {

    var script_tag = document.createElement('script');
    script_tag.setAttribute("type", "text/javascript");
    script_tag.setAttribute("src",
        "http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js");

    // Try to find the head, otherwise default to the documentElement
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

    if (script_tag.readyState) {
        script_tag.onreadystatechange = function () { // For old versions of IE
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                scriptLoadHandler();
            }
        };
    } else { // Other browsers
        script_tag.onload = scriptLoadHandler;
    }
} else {
    // The jQuery version on the window is the one we want to use
    jQueryEg = window.jQuery;
    scriptLoadHandler();
}

在任何一种情况下,我们都将变量jQueryEg设置为我们决定使用的jQuery,以便我们可以避免冲突。

如果尚未加载jQuery,一切都很花哨。但是如果加载旧版本,我们在尝试加载其他库(如jQuery-ui)时会遇到冲突。

为此,我们将window.jQuery设置为新加载的jQuery,这样当我们加载jquery-ui和bootstrap.js时,它们对window.jQuery或$的引用指向正确的版本。

问题是,有时页面的其他部分在我们将window.jQuery设置为导致问题的版本的同时调用jQuery。

关于如何避免这些冲突的任何想法?

jQueryEg = window.jQuery.noConflict(true);
window.jQueryEg = jQueryEg;

// jquery-ui reference window.jQuery so we need to set that to our new jquery for a sec

if (jQueryEg.ui == undefined || jQueryEg.ui.datepicker == undefined) {
    var otherjQuery = window.jQuery;
    window.jQuery = jQueryEg;

    var script_tag = document.createElement('script');
    script_tag.setAttribute("type", "text/javascript");
    script_tag.setAttribute("src",
        "//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js");
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

    script_tag.onload = function () {
        window.jQuery = otherjQuery;
        main();
    };

}

2 个答案:

答案 0 :(得分:4)

一旦遇到a similar issue。看一下jQuery-UI代码,我注意到它全部包含在一个立即调用的函数表达式中(或者我自己包装它?我不记得了):

( function ( jQuery, undefined ){
  // Code here...
})( jQuery );

创建私有作用域。所以我的解决方案是

  1. 将当前jQuery保存到jQuery_OLD
  2. 加载新的jQuery版本
  3. 加载jQuery-UI,让它获取兼容版本
  4. 恢复旧的jQuery
  5. 所以以下给出了想法

    <script src="jquery-1.4.js"></script>
    <script>
        var jQuery_1_4 = jQuery.noConflict();
    </script>
    <script src="jquery-1.8.js"> </script>
    <!-- load jquery UI -->
    <script src="jquery-ui.js"> </script>
    <!-- restore window.jQuery -->
    <script>
        jQuery = jQuery_1_4;
    </script>
    

答案 1 :(得分:0)

之前遇到过这种情况,最终确定的是你可能已经知道的,并且不想听到:在加载多个版本的外部库时,没有好办法避免所有边缘情况这样,由于你已经指定的原因。所涉及的并发症摘要如下:

  • 主要问题当然是:外部脚本的加载本质上是异步的,并且没有“只是在执行之前”/“刚执行之后”回调以确保所有内容都很好地包装。即:没有办法“包围”动态加载的代码。
  • 脚本在直接放入文档时按顺序执行,但没有办法根据另一个确定的内容有条件地加载脚本。
  • 最后,出于用户友好性原因(即:允许网络上的随机用户使用代码知识为零而且没有支持人员的代码段),“确保此片段在之前粘贴”等限制任何其他脚本!“马上就出来了。即使他们可以工作(*他们不会,真的看到其他两点),他们也会被忽略,特别是那些没有完全控制他们页面的人。

不幸的是,唯一的答案显而易见:在您自己的服务器上修改了库的版本。

当然,您无需一直提供这些版本,因此您仍然可以使用Google的CDN。同时,您仍然可以使用自己的CDN来提供修改后的版本。要遵循的主要准则是:

  1. 在加载整个页面后(使用onDOMReady等)运行脚本,以确保在“包含”自己的脚本之后不会发生冲突。
  2. 确定是否可能发生冲突。在这些情况下提供修改后的版本,否则从公共CDN提供服务。
  3. 经常检查与其他库的兼容性。您的代码将随着时间的推移而发展,就像您使用的库一样。 “确定是否存在冲突”步骤需要准确才能实现。谨慎一点:如果您不确定,请提供您自己的版本。
  4. 总是为贴纸提供一个简单的选项,让“总是使用修改后的版本”,以防您的检测以某种方式失败。
  5. 始终使用适当的compressed提供脚本的uglifiedcache headers版本,以减轻您自己服务器的负担。
  6. 您通常会发现自己服务器上的点击次数实际上相当少。一如既往,不要相信我:保持自己的真实场景统计数据!