【问题标题】:Loading a second version of jQuery, and other libraries along with it加载第二个版本的 jQuery 和其他库
【发布时间】:2012-09-21 04:47:12
【问题描述】:

我正在制作一个包含 sn-p 代码的小部件,以放入您的网站,然后通过 js 拉入内容。这是一个示例 sn-p:

<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();
    };

}

【问题讨论】:

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


    【解决方案1】:

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

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

    创建私有范围。所以我的解决方案是

    1. 将当前jQuery保存到jQuery_OLD
    2. 加载新的 jQuery 版本
    3. 加载jQuery-UI,让它抓取兼容版本
    4. 恢复旧jQuery

    所以下面给出了这个想法

    <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>
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      1. 在加载整个页面后运行您的脚本(使用 onDOMReady 等),以确保在包含您自己的脚本“之后”不会发生冲突。
      2. 确定是否可能发生冲突。在这些情况下提供修改后的版本,否则从公共 CDN 提供。
      3. 经常检查与其他库的兼容性。您的代码会随着时间的推移而发展,就像您使用的库一样。 “确定是否可能发生冲突”步骤需要准确才能使其正常工作。请谨慎行事:如果您不确定,请提供您自己的版本。
      4. 始终为粘贴者提供一个简单的选项,让他们说“始终使用修改后的版本”,以防您的检测以某种方式失败。
      5. 始终为您的脚本提供compresseduglified 版本以及适当的cache headers,以减少您自己的服务器上的负载。

      相对而言,您通常会发现您自己的服务器上的点击次数实际上非常少。一如既往,不要相信我:根据您自己的真实场景进行统计!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-24
        • 2015-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多