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



我正在制作一个小部件,它由一段代码组成,放在你的网站上,然后通过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还没有加载,那么一切都很顺利。但是,如果加载了旧版本,我们在尝试加载其他库(如jQueryui)时会遇到冲突。

为此,我们将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();
};
}

有一次我遇到了类似的问题。查看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>

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

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

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

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

  1. 在加载整个页面后运行脚本(使用onDOMReady等),以确保在包含您自己的脚本后不会发生冲突
  2. 确定是否可能发生冲突。在这些情况下提供您的修改版本,否则从公共CDN提供
  3. 经常检查与其他库的兼容性。您的代码会随着时间的推移而发展,就像您使用的库一样。"确定是否可能发生冲突"的步骤需要准确,才能起作用。谨慎的一面是错误的:如果你不确定,就提供你自己的版本
  4. 始终为粘贴器提供一个简单的选项,让其说"始终使用修改后的版本",以防检测失败
  5. 始终提供压缩的、未经验证的脚本版本,并提供适当的缓存头,以减少您自己服务器上的负载

相比之下,您通常会发现自己服务器上的点击次数实际上非常少。和往常一样,不要相信我:把统计数据保存在你自己的真实场景中!

相关内容

  • 没有找到相关文章

最新更新