Коллапс Bootstrap конфликтует с несколькими jquery и bootstrap.js; требовать.JS


У меня есть веб-приложение (назовем его WA1), которое использует RequireJS для загрузки jQuery и Bootstrap.JS. Это приложение будет встроено в один файл (main.построенный.js) и выполняется внутри элемента страницы в другом веб-приложении (WA2).

(WA1 также может работать автономно - не будучи встроенным в WA2)

WA2 загружает jQuery и Bootstrap.js нормально, но главное.построенный.файл js также содержит jQuery и Bootstrap.JS.

Часть пользовательского интерфейса WA1 содержит элемент Bootstrap collapse. То действия сворачивания / разукрупнения инициируются атрибутами данных, помещенными в html. Если вы посмотрите на эту скрипку , элемент, который должен коллапсировать, не может коллапсировать - я думаю, потому что действие коллапса запускается дважды-один раз слушателями в Bootstrap WA2.файл js, и один раз слушателями в главном.построенный.файл js.

Я хотел бы, чтобы коллапс работал правильно, но у меня нет возможности удалить Bootstrap.js из WA2. Не имею возможность использовать RequireJS в WA2.

Есть ли способ для WA1 не загружать jQuery и Bootstrap.js с require.js, но разрешить модули, загруженные через require.js использовать jQuery и Bootstrap, которые будут загружаться нормально (без RequireJS)? Если нет, то может ли jQuery $.noconflict() вообще помочь? Я не очень хорошо знаю, как это работает.

3 2

3 ответа:

В итоге я сделал следующее:

  • Перед загрузкой любых модулей require (включая jQuery) я проверяю, существует ли уже jQuery (он существует, если я работаю в WA2). Если да, то я устанавливаю $isloaded в true.

  • После того, как потребуется бутстрэп.js загружается, если $isloaded является true, я устанавливаю $.fn.collapse = function(){}.

Таким образом, только $.fn.функция collapse в загруженном WA2 jquery / bootstrap что-то сделает. Это выглядит немного банально, но сработало.

Скрипка: http://jsfiddle.net/wSPXP/17/

Вот один из способов сделать то, что, как я понимаю, вы хотите сделать. Операторы 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. JQuery и Bootstrap, загруженные для WA2, должныуже быть загружены до запуска этого кода.

Как это работает:

  1. Он определяет, загружен ли jQuery, проверяя, что $ установлен.

  2. Он определяет, загружается ли Bootstrap, проверяя, является ли $.fn.popover существует. Я не знаю санкционированного способа проверить, был ли загружен Bootstrap. Я проверил код и не увидел $.fn.bootstrap или чего-то подобного, что предположительно было бы уникальным для Bootstrap. Он устанавливает метод popover, так что это то, что я использую.

  3. Когда обнаруживается, что они уже присутствуют, карта для "*" заполняется так, что когда требуется jquery, вместо этого загружается jquery-fake, и аналогично для bootstrap.

  4. Два поддельных модуля-это те, которые вы видите. определено в начале кода. На самом деле они ничего не загружают.

Скрипка

У меня уже была подобная проблема в прошлом. Меня до сих пор раздражает, что я с ним столкнулся, но я рад, что не один такой.

Способ, которым я обошел его, был именно таким, как вы определили, чтобы использовать $.noConflict(true).

Вам понадобятся два сценария require config.

Для WA1 вам потребуется настроить require обычным способом. Это позволит вам запускать его как отдельное веб-приложение, независимое от WA2:

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

Для WA2 вам потребуется настроить требовать примерно так:

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, ваши define функции в WA1 будут вызывать jquery-no-conflict.js

Единственное, что мне не нравится в этом шаблоне, это то, что ваш HTML для WA1 теперь содержит две ссылки на jQuery, хотя глобальный $ все равно будет указывать на первый загруженный экземпляр jQuery.

Хотя я еще не пробовал, вероятно, вы можно применить аналогичный шаблон, используя Bootstrap noConflict

Пожалуйста, дайте мне знать, как у вас дела.