Подтвердить что ты не робот

Загрузочный лоток Shim Twitter для RequireJS

RequireJS docs говорят, что для поддержки более старых версий IE вам необходимо настроить enforceDefine: true.

Итак, если вы хотите поддерживать Internet Explorer, ломать ошибки загрузки и иметь модульный код либо через прямые вызовы define(), либо в конфигурацию shim, всегда устанавливайте принудительное соответствие для true. См. Следующий раздел для примера.

ПРИМЕЧАНИЕ. Если вы установите для параметра enforceDefine: true и используете data-main = "" для загрузки основного JS-модуля, то этот основной JS-модуль должен вызывать define() вместо require() для загрузки необходимого ему кода, Основной JS-модуль может по-прежнему вызывать require/requirejs для установки значений конфигурации, но для загрузки модулей он должен использовать define().

Так как Twitter Bootstrap не является модулем AMD, мне нужно закрепить его, чтобы он работал. Вот как я его настраиваю:

<script type="text/javascript">
    var require = {
        paths: {
            "bootstrap": "../bootstrap",
            "jquery": "../jquery-1.8.2"
        },
        shim: {
            "bootstrap": ["jquery"]
        },
        enforceDefine: true
    };
</script>

Позже, когда мой модуль хочет загрузочную загрузку в качестве зависимости, я все равно получаю сообщение об ошибке:

Error: No define call for bootstrap

http://requirejs.org/docs/errors.html#nodefine

Если я правильно понял документы, enforceDefine должен игнорировать прокладки, но это не так.

Что я здесь делаю неправильно?

4b9b3361

Ответ 1

В соответствии с документами, которые вызывают ошибка, если "Script был частью конфигурации shim, которая указала глобальное свойство строки, которое можно проверить для загрузки, и эта проверка завершилась неудачно".

Чтобы исправить это, вам нужно добавить значение экспорта в конфигурацию shim, чтобы RequireJS мог проверить, была ли успешно загружена script. В случае Bootstrap, который немного сложнее, поскольку Bootstrap не "экспортирует" глобальную переменную ownt только кучу jQuery-плагинов, но вы можете использовать любой из этих плагинов в качестве значения экспорта, например. $.fn.popover:

{
    paths: {
        "bootstrap": "../bootstrap",
        "jquery": "../jquery-1.8.2"
    },
    shim: {
        "bootstrap": {
          deps: ["jquery"],
          exports: "$.fn.popover"
        }
    },
    enforceDefine: true
}

Ответ 2

Вместо того, чтобы делать магию с помощью прокладки, я преобразовал бутстрап JS в модуль:

define([ "jquery" ], function($) {
  // bootstrap JS code
});

Все, что я нашел на форумах и в stackoverflow, не работало для меня, потому что я получаю jQuery из CDN. Я предполагаю, что я попал в проблему, как описано в документе requireJS, в http://requirejs.org/docs/api.html

Не смешивайте загрузку CDN с конфигурацией прокладки в сборке. Пример сценария: вы загружаете jQuery из CDN, но используете конфигурацию shim для загрузки чего-либо как запасная версия Backbone, которая зависит от jQuery. Когда вы это сделаете построить, обязательно встроить jQuery в встроенный файл и не загружать это из CDN. В противном случае Backbone будет встроен в встроенный файл и он будет выполняться перед загрузкой загруженного CDN jQuery. Это потому что конфигурация прокладки просто задерживает загрузку файлов до тех пор, пока загружаются зависимости, но не выполняет автоматическую упаковку определения. После сборки зависимости уже встроены, конфигурация прокладки не может отложить выполнение кода non-define() 'd до конца. Модули define() 'd работают с загруженным кодом CDN после сборки, потому что они надлежащим образом обертывают свой источник в функции factory, которая будет не выполняются до загрузки зависимостей. Итак, урок: shim config является мерой стоп-кадра для немодульного кода, устаревшего кода. define() 'd лучше.

Преобразование бутстрапа в обычный модуль AMD и удаление конфигурации shim разрешили его для меня. Единственный недостаток: вы не можете загрузить бутстрап из бутстрапа CDN.

Ответ 3

Я использую эту конфигурацию в своем проекте:

startup.js

require.config({
    paths: {
        /* other paths are omitted */
        'bootstrap': '../libs/bootstrap'
    },
    shim: {
        'bootstrap/bootstrap-slider': { deps: ['jquery'], exports: '$.fn.slider' }, 
        'bootstrap/bootstrap-affix': { deps: ['jquery'], exports: '$.fn.affix' },
        'bootstrap/bootstrap-alert': { deps: ['jquery'], exports: '$.fn.alert' },
        'bootstrap/bootstrap-button': { deps: ['jquery'], exports: '$.fn.button' },
        'bootstrap/bootstrap-carousel': { deps: ['jquery'], exports: '$.fn.carousel' },
        'bootstrap/bootstrap-collapse': { deps: ['jquery'], exports: '$.fn.collapse' },
        'bootstrap/bootstrap-dropdown': { deps: ['jquery'], exports: '$.fn.dropdown' },
        'bootstrap/bootstrap-modal': { deps: ['jquery'], exports: '$.fn.modal' },
        'bootstrap/bootstrap-popover': { deps: ['jquery'], exports: '$.fn.popover' },
        'bootstrap/bootstrap-scrollspy': { deps: ['jquery'], exports: '$.fn.scrollspy'        },
        'bootstrap/bootstrap-tab': { deps: ['jquery'], exports: '$.fn.tab' },
        'bootstrap/bootstrap-tooltip': { deps: ['jquery'], exports: '$.fn.tooltip' },
        'bootstrap/bootstrap-transition': { deps: ['jquery'], exports: '$.support.transition' },
        'bootstrap/bootstrap-typeahead': { deps: ['jquery'], exports: '$.fn.typeahead'  },
    }
});

require(['domReady', 'app'], function(domReady, app) {
    domReady(function() {
        app.init();
    });
});

то в моем коде я использую это:

define(['jquery', 'underscore', 'backbone', 'text!templates/photos-list.html'], function($, _, Backbone, html) {
    var PhotosListView = Backbone.View.extend({
        viewImageFullscreen: function(e) {
            e.preventDefault();

            require(['bootstrap/bootstrap-modal', 'text!templates/photo-modal.html'], function(modal, htmlModal) {
                 var modalTemplate = _.template(htmlModal, options);
                 $('body').append(modalTemplate);

                 // setup
                 $(selector + '_modal').modal({
                     backdrop: true,
                     keyboard: true,
                     show: false
                 }).css({
                     'width': function() { return ($(document).width() * 0.55) + 'px'; },
                     'margin-left': function() { return -($(this).width() * 0.5); }
                 });

                 // trigger `modal` 
                 $(selector + '_modal').modal('show');
             }); // require() call
         // ...

Ответ 4

@lexeme и @benjaminbenben как обматывать эту концепцию в плагине RequireJS, который создает прокладку, требует jQuery, а также возвращает jQuery, поэтому вам не нужно включать это вручную?

Чтобы использовать компонент bootstrap, вы просто используете:

define(['bootstrap!tooltip'], function($){
  $('[data-toggle="tooltip"]').tooltip();
});

И вы должны использовать этот require-bootstrap-plugin, чтобы он работал.