Requirejs, почему и когда использовать конфигурацию прокладки


97

Я прочитал документ requirejs отсюда API

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

но я не получаю регулировочную шайбу части. почему я должен использовать прокладку и как мне настроить, могу ли я получить дополнительные разъяснения

пожалуйста, кто-нибудь может объяснить на примере, почему и когда мы должны использовать прокладку. Спасибо.

Ответы:


110

В основном прокладка используется с библиотеками, которые не поддерживают AMD, но вам необходимо управлять их зависимостями. Например, в приведенном выше примере Backbone и Underscore: вы знаете, что Backbone требует Underscore, поэтому предположим, что вы написали свой код следующим образом:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS будет запускать асинхронные запросы как для Underscore, так и для Backbone, но вы не знаете, какой из них вернется первым, поэтому возможно, что Backbone попытается что-то сделать с Underscore до его загрузки.

ПРИМЕЧАНИЕ: этот пример подчеркивания / магистрали был написан до того, как обе эти библиотеки поддержали AMD. Но этот принцип верен для любых современных библиотек, не поддерживающих AMD.

Хук "init" позволяет вам делать другие продвинутые вещи, например, если библиотека обычно экспортирует две разные вещи в глобальное пространство имен, но вы хотите переопределить их в одном пространстве имен. Или, может быть, вы хотите исправить обезьяны методы в загружаемой библиотеке.

Дополнительная информация:


Как и в вашем примере кода, Underscoreи Backboneздесь используется как обычно, что shimделать в этом случае? Могу я использовать require( function() { _.extend({}); })? Это понимает _?
Stiger

«RequireJS будет запускать асинхронные запросы как для Underscore, так и для Backbone» -> Можно ли предотвратить это в случае, если библиотека уже загружена?
Codii

1
@Codii правильно, если библиотека уже загружена, она не запустит другой запрос сервера, но суть RequireJS в том, что вашему коду не нужно заботиться о том, произойдет ли / как это произойдет. Возможно, вы зададите новый вопрос для вашего конкретного случая использования?
Объяснение

63

Согласно документации API RequireJS, оболочка shim позволяет

Настройте зависимости, экспорт и пользовательскую инициализацию для старых традиционных сценариев «глобальных браузеров», которые не используют define () для объявления зависимостей и установки значения модуля.

- Настройка зависимостей

Допустим, у вас есть 2 модуля javascript (moduleA и moduleB), и один из них (moduleA) зависит от другого (moduleB). Оба они необходимы для вашего собственного модуля, поэтому вы указываете зависимости в require () или define ().

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

Но поскольку require следует за AMD, вы не знаете, какой из них будет загружен раньше. Здесь на помощь приходит прокладка.

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

Это гарантирует, что moduleB всегда выбирается до загрузки moduleA.

- Настройка экспорта

Экспорт Shim сообщает RequireJS, какой член глобального объекта (окна, если, конечно, вы находитесь в браузере) является фактическим значением модуля. Допустим, moduleA добавляет себя к window'modA' (точно так же, как jQuery и подчеркивание делают как $ и _ соответственно), затем мы делаем наш экспорт значением 'modA'.

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

Это даст RequireJS локальную ссылку на этот модуль. Глобальный modA тоже будет существовать на странице.

-Пользовательская инициализация для старых скриптов "глобального браузера"

Это, вероятно, самая важная функция конфигурации оболочки, которая позволяет нам добавлять «глобальные браузерные», «не-AMD» скрипты (которые также не следуют модульному шаблону) в качестве зависимостей в нашем собственном модуле.

Допустим, moduleB - это простой старый javascript с двумя функциями funcA () и funcB ().

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

Хотя обе эти функции доступны в области окна, RequireJS рекомендует нам использовать их через их глобальный идентификатор / дескриптор, чтобы избежать путаницы. Поэтому настройте прокладку как

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

Значение, возвращаемое функцией init, используется в качестве значения экспорта модуля вместо объекта, найденного через строку «exports». Это позволит нам использовать funcB в нашем собственном модуле как

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

Надеюсь, это помогло.


3
Легко понять! Один вопрос: в последнем примере просто игнорируется свойство «экспорт»?
Нико Беллик,

Нет, это не игнорируется. Если бы свойство «exports» было проигнорировано в последнем примере, то объект, который вы передаете в качестве параметра (в данном случае «B»), не был бы определен, поскольку moduleB НЕ совместим с AMD и не вернул бы объект для использования RequireJS ( следовательно, "B.funcB" не будет работать).
nalinc

Хм. Я думал, что значение экспорта будет отменено объектом, возвращаемым функцией init. Таким образом, параметром B будет объект {funcA: funcA, funcB: funcB}, а не просто funcB сам по себе. Это не правда?
Нико Беллик,

4
Нико Беллик прав, экспорт игнорируется (я только что это проверил). Объект B - это объект, возвращаемый функцией, указанной в части init. Если вы удалите часть init, объект B станет функцией funcB, поэтому вы просто выполните B () вместо B.funcB (). И, очевидно, в этом случае funcA станет недоступной.
user4205580 04

-2

Вы должны добавить пути в requirejs.config для объявления, например:

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});

1
Этот ответ представляет собой дамп кода, который ничего не делает, чтобы объяснить, «почему и когда использовать конфигурацию прокладки». Если вы редактируете свой ответ, чтобы дать объяснение, убедитесь, что вы добавляете что-то новое, что еще не охвачено более ранними ответами
Луи

copy paste без положительных отзывов
william.eyidi

перед шайбой должна стоять запятая:
Скотт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.