Requirejs, чому і коли використовувати shim config


97

Я читаю документ Requjs звідси 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();
            }
        }
    }
});

але я не отримую шаленої частини. чому я повинен використовувати shim і як слід налаштувати, чи можу я отримати ще одне уточнення

будь-хто, може пояснити на прикладі, чому і коли ми повинні використовувати shim. Дякую.

Відповіді:


110

Основне використання shim - це з бібліотеками, які не підтримують AMD, але вам потрібно керувати їх залежностями. Наприклад, у наведеному вище прикладі Backbone and Underscore: ви знаєте, що Backbone вимагає підкреслення, тому припустимо, що ви написали свій код так:

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

    // do something with Backbone

}

RequireJS запустить асинхронні запити як для підкреслення, так і для хребта, але ви не знаєте, який з них повернеться першим, тому можливо, що Backbone спробує зробити щось із підкресленням перед завантаженням.

ПРИМІТКА: цей приклад підкреслення / опорної кістки був написаний до того, як обидві бібліотеки підтримували AMD. Але цей принцип справедливий для будь-яких бібліотек сьогодні, які не підтримують AMD.

Гак "init" дозволяє робити інші вдосконалені речі, наприклад, якщо бібліотека зазвичай експортує дві різні речі в глобальний простір імен, але ви хочете їх переосмислити під єдиним простором імен. Або, можливо, ви хочете зробити кілька виправлень мавп на методах у бібліотеці, яку ви завантажуєте.

Докладніше:


Як і ти, наприклад, код, Underscoreі Backboneтут використовується як звичайний, що shimробити в цьому випадку? Чи можу я використовувати require( function() { _.extend({}); })? Це розуміє _?
Стігер

"RequireJS запустить асинхронні запити як для підкреслення, так і для хребта" -> Чи можливо це запобігти, якщо бібліотека вже завантажена?
Коді

1
@Codii правильно, якщо бібліотека вже завантажена, вона не запустить інший запит сервера, але суть RequireJS полягає в тому, що ваш код не повинен дбати про те, чи / як це станеться. Можливо, почати нове запитання для конкретного випадку використання?
explunit

63

Відповідно до документації API RequireJS, shim дозволяє вам

Налаштуйте залежності, експорт та ініціалізацію на замовлення для старих, традиційних сценаріїв "глобальних браузерних" скриптів, які не використовують define () для декларування залежностей та встановлення значення модуля.

- Налаштування залежностей

Скажімо, у вас є 2 модулі javascript (moduleA і moduleB), і один з них (moduleA) залежить від іншого (moduleB). Обидва вони необхідні для вашого власного модуля, тому ви вказуєте залежності в Requ () або визначаєте ()

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

Але оскільки вимагає відстежувати AMD, ви не знаєте, який із них можна було б отримати рано. Тут на допомогу приходить шим.

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

})

Це дозволить переконатися, що moduleB завжди отримується перед завантаженням модуляA.

- Налаштування експорту

Експорт Shim повідомляє RequireJS, який член глобального об’єкта (вікно, якщо, звичайно, ви перебуваєте в браузері), є фактичним значенням модуля. Скажімо, модульA додає себе до window"modA" (подібно до того, як jQuery і підкреслення робить як $ і _ відповідно), то ми зробимо наше значення експорту "modA".

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

Це дасть RequireJS локальне посилання на цей модуль. Глобальний мод все ще буде існувати на сторінці.

-Настроювати ініціалізацію для старих "глобальних" браузерів

Це, мабуть, найважливіша особливість конфігурації shim, яка дозволяє нам додавати "глобальний браузер", "не 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 використовується як значення експорту модуля замість об'єкта, знайденого через рядок 'export'. Це дозволить нам використовувати funcB у власному модулі як

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

Сподіваюся, що це допомогло.


3
Легко зрозуміти! Одне запитання: в останньому прикладі властивість "експорту" просто ігнорується?
Ніко Белік

Ні, його не ігнорують. Якби властивість "експортувати" була проігнорована в останньому прикладі, то об'єкт, який ви передаєте як параметр (у цьому випадку "B"), не буде визначено, оскільки moduleB не сумісний з AMD і не повернув би об'єкт для використання RequireJS ( отже, "B.funcB" не працює).
nalinc

Хм. Я думав, що значення експорту буде перевершено об'єктом, який повертається у функції init. Отже параметр B був би об'єктом {funcA: funcA, funcB: funcB}, а не просто funcB сам по собі. Це неправда?
Ніко Белік

4
Niko Bellic має рацію, експорт IS проігнорований (я щойно це перевірив). Об'єкт B - це об'єкт, повернутий функцією, визначеною у частині 'init'. Якщо ви видалили 'init' частину, об'єкт B став би функцією funcB, тож ви просто зробите B () замість B.funcB (). І очевидно, що funcA стане в цьому випадку недоступним.
user4205580

-2

Ви повинні додати шляхи в Requjs.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
Ця відповідь - це дамп коду, який нічого не пояснює "чому і коли використовувати shim config". Якщо ви редагуєте свою відповідь, щоб дати пояснення, переконайтеся, що ви додали щось нове, що вже не охоплено попередніми відповідями
Луї

Скопіюйте пасту без будь-яких позитивних відгуків
william.eyidi

повинна бути комою перед шим:
Скотт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.