jQuery noconflict,bootstrap和requirejs

时间:2015-06-24 07:37:55

标签: javascript jquery twitter-bootstrap requirejs

我正在开发的环境是使用jQuery 1.7.1,而我需要特别使用jQuery 2.1.3。但是当我使用2.1.3一些遗留代码中断时(因为它使用1.7.1)所以我不得不在2.1.3上使用jQuery.noconflict

的jquery-private.js:

define(["jquery"], function(jQuery){
    return jQuery.noConflict(true);
});

然后在我的requirejs配置文件中我有这个:

config.js:

requirejs.config({
    baseUrl: '../',
    paths: {
        'jquery': 'js/jquery/jquery',
        'jqueryui': 'js/jquery-ui/jquery-ui',
        'bootstrap': 'js/bootstrap',
    },
    map: {
        // '*' means all modules will get 'jquery-private'
        // for their 'jquery' dependency.
        '*': {
            'jquery': 'jquery-private'
        },

        // 'jquery-private' wants the real jQuery module
        // though. If this line was not here, there would
        // be an unresolvable cyclic dependency.
        'jquery-private': {
            'jquery': 'jquery'
        }
    },
    shim: {
        'bootstrap': {
            deps: ['jquery']
        }
    }
});

所以当我需要bootstrap时

widget.js:

require([
    "jquery",
    "bootstrap"
], function(jqr){
    // SOME CODE
});

我收到错误:

未捕获错误:Bootstrap的JavaScript需要jQuery版本1.9.1或更高版本

所以bootstrap正在上升1.7.1。

如何在不更改bootstrap.js文件的情况下进行拾取2.1.3?

1 个答案:

答案 0 :(得分:1)

为什么会失败?

您当前的尝试无法正常工作,因为您的jquery-private设置确保只要jQuery作为RequireJS模块加载,就会调用noConflict()。只要使用RequireJS加载的代码通过define调用(例如define(['jquery'], function ($) {)引用jQuery,就没有问题。但是,任何填充的代码都将引用$jQuery全局变量,因此将引用1.7.1版本。

解决方案

没有任何其他约束,首选解决方案是让整个代码库使用相同的jQuery版本。将1.7.1升级到1.x系列中的最新版本,然后使用它。根据{{​​3}},2.x与1.x系列中相对较新的版本之间没有API差异(我会说1.9.x及更高版本)。当然,这意味着可能必须更新依赖于1.7.1的代码以使用1.x系列中的最新jQuery。

我建议升级到2.x系列但你在评论中提到需要与IE 6和7的兼容性。注意:如果你设法让1.7.1和2.1.3加载到同一页面,使用2.1.3的那部分代码不会'与IE 6和7兼容,因此页面实际上不再与IE 6和7兼容。

要使用此解决方案,除了必须对升级进行的更改外,您还必须:

  1. 确保jQuery在 RequireJS之前加载。否则,它将检测RequireJS并调用define但是它不会可靠地可用于未加载RequireJS的代码。 (我说它不会被"可靠地使用"因为虽然加载jquery模块后,jQuery$全局变量将存在,问题是,没有加载RequireJS的代码不能等待以使RequireJS加载jQuery。因此,除非你努力编写自己的同步代码,否则它将无法可靠地工作。)

  2. 创建一个RequireJS模块,它只是在RequireJS可以将RequireJS模块作为模块使用之前加载jQuery,因此:

    define('jquery', function () { return jQuery; });
    

    这可以在您致电require.config之前发出。这造成了一个假的" jquery模块仅返回全局jQuery符号。 (它也可以返回$。)

  3. 替代?

    我没有看到上面解决方案的强大替代方案。提出可证明另一种方法的概念证明并不困难。但是,只要您尝试在实际项目中使用它,它就会失败。问题是RequireJS本质上是异步的,所以你不能开始弄乱$jQuery全局变量来设置你想要的方式,并确保你想要发生的一切都发生在 at你希望它发生的时间。此外,在RequireJS之前加载的任何代码恰好发起可能与RequireJS交错的异步操作。模块加载会将一个猴子扳手投入整个操作。我宁愿避免提出一些解决方案,这些解决方案一旦从概念证明转向现实世界的应用程序就会失败。