Wymaga, dlaczego i kiedy używać shim config

97

Przeczytałem dokument requirejs z tutaj 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();
            }
        }
    }
});

ale nie dostaję w tym części podkładki . dlaczego powinienem używać podkładki i jak skonfigurować, czy mogę uzyskać więcej wyjaśnień

czy ktoś może wyjaśnić na przykładzie, dlaczego i kiedy powinniśmy używać podkładki. dzięki.

Anil Gupta
źródło

Odpowiedzi:

110

Podstawowym zastosowaniem podkładki jest użycie bibliotek, które nie obsługują technologii AMD, ale trzeba zarządzać ich zależnościami. Na przykład w powyższym przykładzie Backbone and Underscore: wiesz, że Backbone wymaga Underscore, więc załóżmy, że napisałeś swój kod w ten sposób:

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

    // do something with Backbone

}

RequireJS uruchomi asynchroniczne żądania zarówno dla Underscore, jak i Backbone, ale nie wiesz, które z nich wróci jako pierwsze, więc możliwe, że Backbone spróbuje coś zrobić z Underscore, zanim zostanie załadowany.

UWAGA: ten przykład podkreślenia / szkieletu został napisany, zanim obie te biblioteki obsługiwały AMD. Ale ta zasada odnosi się do wszystkich bibliotek, które nie obsługują technologii AMD.

Hak "init" pozwala ci robić inne zaawansowane rzeczy, np. Jeśli biblioteka normalnie eksportuje dwie różne rzeczy do globalnej przestrzeni nazw, ale chcesz przedefiniować je w jednej przestrzeni nazw. A może chcesz wykonać małpę poprawiania metod w ładowanej bibliotece.

Więcej informacji:

explunit
źródło
Podobnie jak w przypadku przykładowego kodu, Underscorei Backbonetutaj używamy jak normalnie, co shimw tym przypadku? Czy mogę użyć require( function() { _.extend({}); })? Czy to rozumie _?
Stiger
„RequireJS uruchomi asynchroniczne żądania zarówno dla Underscore, jak i Backbone” -> Czy można temu zapobiec w przypadku, gdy biblioteka jest już załadowana?
Codii
1
@Codii racja, jeśli biblioteka jest już załadowana, nie uruchomi kolejnego żądania serwera, ale celem RequireJS jest to, że twój kod nie musi dbać o to, czy / jak to się stanie. Może zacznij nowe pytanie dla swojego konkretnego przypadku użycia?
otwarcie
63

Zgodnie z dokumentacją API RequireJS, podkładka pozwala

Skonfiguruj zależności, eksporty i niestandardową inicjalizację dla starszych, tradycyjnych skryptów „przeglądarek globalnych”, które nie używają funkcji define () do deklarowania zależności i ustawiania wartości modułu.

- Konfigurowanie zależności

Powiedzmy, że masz 2 moduły javascript (modułA i modułB), a jeden z nich (modułA) zależy od drugiego (modułB). Oba są niezbędne dla twojego własnego modułu, więc określasz zależności w require () lub define ()

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

Ale ponieważ wymaga podążania za AMD, nie masz pojęcia, który z nich zostanie pobrany wcześniej. Tutaj z pomocą przychodzi podkładka.

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

})

Dzięki temu modułB będzie zawsze pobierany przed załadowaniem modułu A.

- Konfiguracja eksportu

Eksport Shim mówi RequireJS, który element w obiekcie globalnym (okno, zakładając, że jesteś w przeglądarce, oczywiście) jest rzeczywistą wartością modułu. Powiedzmy, że modułA dodaje się do elementu window„modA” (podobnie jak jQuery i podkreślenie robi odpowiednio jako $ i _), a następnie ustawiamy wartość eksportu jako „modA”.

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

Da RequireJS lokalne odniesienie do tego modułu. Globalny modA będzie nadal istniał na stronie.

- Niestandardowa inicjalizacja dla starszych skryptów „globalnych przeglądarki”

Jest to prawdopodobnie najważniejsza cecha konfiguracji shim, która pozwala nam dodawać skrypty „globalne przeglądarki”, „inne niż AMD” (które również nie są zgodne ze wzorcem modularnym) jako zależności w naszym własnym module.

Powiedzmy, że moduleB to zwykły stary javascript z tylko dwiema funkcjami funcA () i funcB ().

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

Chociaż obie te funkcje są dostępne w zakresie okna, RequireJS zaleca, abyśmy używali ich poprzez ich globalny identyfikator / uchwyt, aby uniknąć nieporozumień. Więc konfigurując podkładkę jako

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

Wartość zwracana przez funkcję init jest używana jako wartość eksportu modułu zamiast obiektu znalezionego za pośrednictwem ciągu znaków „export”. Umożliwi nam to użycie funcB w naszym własnym module jako

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

Mam nadzieję, że to pomogło.

nalinc
źródło
3
Łatwy do zrozumienia! Jedno pytanie: czy w ostatnim przykładzie właściwość „export” jest po prostu ignorowana?
Niko Bellic
Nie, to nie jest ignorowane. Gdyby właściwość „export” została zignorowana w ostatnim przykładzie, obiekt przekazany jako parametr (w tym przypadku 'B') byłby niezdefiniowany, ponieważ modułB NIE jest zgodny z AMD i nie zwróciłby obiektu do użycia przez RequireJS ( stąd „B.funcB” nie będzie działać).
nalinc
Hmm. Myślałem, że wartość eksportu zostanie zastąpiona przez obiekt, który jest zwracany w funkcji init. Zatem parametr B byłby obiektem {funcA: funcA, funcB: funcB}, a nie po prostu samym funcB. Czy to nieprawda?
Niko Bellic
4
Niko Bellic ma rację, eksport JEST ignorowany (właśnie to przetestowałem). Obiekt B jest obiektem zwracanym przez funkcję określoną w części 'init'. Gdybyś usunął część „init”, obiekt B stałby się funkcją funcB, więc po prostu wykonałbyś B () zamiast B.funcB (). I oczywiście funcA stałby się w takim przypadku niedostępny.
user4205580
-2

Aby zadeklarować, musisz dodać ścieżki w requirejs.config, przykład:

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();
            }
        }
    }
});
Rachman Anwar
źródło
1
Ta odpowiedź to zrzut kodu, który nie wyjaśnia, „dlaczego i kiedy używać konfiguracji shim”. Jeśli edytujesz odpowiedź, aby podać wyjaśnienie, upewnij się, że dodajesz coś nowego, co nie jest już objęte wcześniejszymi odpowiedziami
Louis
kopiuj wklej bez żadnych pozytywnych opinii
william.eyidi
przed podkładką powinien być przecinek:
Scott