Bootstrap Collapse与多个jquery和bootstrap.js冲突; require.js

时间:2014-05-21 21:01:23

标签: jquery twitter-bootstrap requirejs amd

我有一个使用RequireJS加载jQuery和Bootstrap.js的Web应用程序(我们称之为WA1)。此应用程序内置于单个文件(main.built.js)中,并在不同Web应用程序(WA2)上的页面元素内运行。

(WA1也可以独立运行 - 无需内置到WA2中)

WA2正常加载jQuery和Bootstrap.js,但main.built.js文件也包含jQuery和Bootstrap.js。

WA1的部分UI包含一个Bootstrap折叠元素。折叠/取消碰撞的操作由放在html中的数据属性触发。如果你看this fiddle,那么应该崩溃的元素就不会崩溃 - 我认为因为崩溃动作被触发了两次 - 一次是由WA2 Bootstrap.js文件中的监听器触发,一次是由侦听器触发main.built.js文件。

我希望崩溃正常运行,但我没有从WA2中删除Bootstrap.js的选项。我也没有选择在WA2中使用RequireJS。

有没有办法让WA1不用require.js加载jQuery和Bootstrap.js,但是允许通过require.js加载的模块使用jQuery和Bootstrap来正常加载(没有RequireJS)?如果没有,jQuery的$.noconflict()可以提供帮助吗?我并不熟悉它是如何运作的。

3 个答案:

答案 0 :(得分:3)

我最终做了以下事情:

  • 在我加载任何require模块(包括jQuery)之前,我检查jQuery是否已经存在(如果我在WA2中运行它确实存在)。如果有,我将$isloaded设置为true

  • 加载了require bootstrap.js后,如果$isloadedtrue,我设置$.fn.collapse = function(){}

这样,只有WA2加载的jquery / bootstrap中的$ .fn.collapse函数才能执行某些操作。感觉有点hacky,但它确实有效。

小提琴:http://jsfiddle.net/wSPXP/17/

答案 1 :(得分:1)

这是一种做我理解你想做的事情的方法。 console.log语句只是检查发生了什么。如果我在您的小提琴require调用之前(以及require.config调用之后)添加以下代码段,则折叠元素可以正常工作:

(function () {
    define("jquery-fake", [], function () { 
        console.log("jquery-fake"); 
        // Just return the already loaded jQuery.
        return $; 
    });

    define("bootstrap-fake", ["jquery"], function () { 
        console.log("bootstrap-fake");
        // Nothing to be done here.
    });

    var map = {};

    if ($)
        map.jquery = "jquery-fake";

    if ($.fn.popover)
        map.bootstrap = "bootstrap-fake";

    require.config({ map: { "*": map } });
})();

如果您不从“外部资源”列表中删除jQuery,则上述操作无效。现在,在 RequireJS开始加载任何东西之前,它被加载两次

要件:

  1. 这必须在您最初的require.config电话之后,但在您开始加载任何内容之前显示。

  2. 在此代码运行之前,必须加载为WA2加载的jQuery和Bootstrap。

  3. 工作原理:

    1. 它通过检查是否已设置$来检测是否加载了jQuery。

    2. 通过检查$.fn.popover是否存在来检测是否加载了Bootstrap。我不知道检查Bootstrap是否已加载的制裁方法。我检查了代码并没有看到$.fn.bootstrap或类似的任何可能是Bootstrap独有的东西。它确实设置了popover方法,这就是我使用的方法。

    3. 如果检测到这些内容已经存在,则会填充“*”的地图,以便在需要加jquery jquery-fake时加载bootstrap,同样加载{{1}}

    4. 这两个假模块是您在代码早期定义的模块。它们实际上并没有加载任何东西。

    5. Fiddle

答案 2 :(得分:0)

我过去也遇到过类似的问题。直到今天我才遇到它让我很烦,但我很高兴知道我并不是唯一的一个。

我解决这个问题的方式,正如您所确定的那样,使用$.noConflict(true)

您需要两个require配置脚本。

对于WA1,您需要以正常方式配置require。这使您可以将其作为独立的Web应用程序运行,独立于WA2:

require.config({
    paths: {
        'jquery': '//code.jquery.com/jquery-1.11.0.min.js',
        //...
    }
});

对于WA2,您需要像这样配置require:

require.config({
    paths: {
        'jquery': 'src/jquery-no-conflict',
        'jquery-src': '//code.jquery.com/jquery-1.11.0.min.js',
        //...
    }
});

在jquery-no-conflict.js中,我们加载jQuery,但将全局$还原为WA2加载的版本:

define(['jquery-src'], function ($) {

    //unload the newly loaded version of jQuery
    $.noConflict(true);

    //return the original version
    return $;
});

现在,从WA2加载时,WA1中的define函数将调用jquery-no-conflict.js

我唯一不喜欢这种模式的是,你的WA1的HTML现在包含两个对jQuery的引用,尽管全局$仍将指向第一个加载的jQuery实例。

虽然我没有尝试过,但大概你可以使用Bootstrap noConflict

来应用类似的模式

请告诉我你是怎么过的。