Jak sprawić, by wtyczka jQuery była ładowalna za pomocą requirejs

88

Pracuję z requirejs + jquery i zastanawiałem się, czy istnieje sprytny sposób, aby wtyczka jQuery działała dobrze z require.

Na przykład używam jQuery-cookie. Jeśli dobrze zrozumiałem, mogę utworzyć plik o nazwie jquery-cookie.js i wewnątrz zrobić

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});
requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

Zastanawiałem się, czy mógłbym robić rzeczy takie jak jQuery, które wygląda tak:

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
    define( "jquery", [], function () { return jQuery; } );
}

lub jeśli jest to jedyny sposób, aby wtyczki jQuery były kompatybilne z requirejs lub dowolnym amd

Nicola Peluchetti
źródło

Odpowiedzi:

67

Musisz tylko to zrobić

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});

na końcu jquery-cookie.js LUB

requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

gdziekolwiek, zanim włączysz plik cookie jquery (na przykład wszędzie tam, gdzie wskazuje główny plik danych).

Ostatni wysłany przez ciebie blok kodu jest dobry dla rzeczy takich jak jQuery, które są redystrybuowane i mogą, ale nie muszą, znajdować się w środowisku AMD. Idealnie byłoby, gdyby każda wtyczka jQuery miała już taką konfigurację.

Wolę, aby dołączone biblioteki były tak nieskażone, jak to tylko możliwe, więc globalna konfiguracja podkładek raz na stronę wydaje mi się najczystszym rozwiązaniem . W ten sposób aktualizacje są bezpieczniejsze, a CDN stają się możliwe.

Hans
źródło
1
Jeśli nie zrobić zarówno zdefiniować i podkładka rzeczy nie działają, mam $ .cookie nie jest komunikat o błędzie funkcja
Nicola Peluchetti
Z mojego doświadczenia wynika, że ​​nie zwracanie czegokolwiek z funkcji definiującej nie wystarczy, requirejs nie rozpozna załadowania modułu. Można to obejść za pomocą shim: {plugins: {
depend
Należy pamiętać, że skrypt wtyczki jQuery musi faktycznie działać. Nie jestem ekspertem, ale znalazłem proste rozwiązanie, w którym masz pojedynczy require(['plugin1', 'plugin2']);itd. Żadne wywołanie zwrotne nie jest przekazywane, więc nic nie będzie działać z wyjątkiem samych skryptów wtyczek. Oznacza to, że następnie dodają się, jQuery.fnwięc wszędzie indziej możesz po prostu wymienić „jquery” jako zależność i zostaną one uwzględnione. Tak jak powiedziałem, jestem w tym całkiem nowy i może być lepsze podejście (na przykład użycie scripttagu), ale to działa.
Joshua Bambrick
3
Josh: Ryzykujesz, że wszystko zostanie załadowane we właściwej kolejności. Niektórzy użytkownicy Twojej witryny prawdopodobnie widzą zepsute rzeczy. Problem nie polega na tym, że wtyczka ładuje się, ale podczas ładowania wtyczki i co jeszcze jest w tym czasie wykonywane. Głównym powodem używania wymagania jest zapewnienie rozsądnej kolejności operacji w oparciu o zależności, a nie domysły.
Hans,
104

Istnieją pewne zastrzeżenia dotyczące używania konfiguracji podkładek w RequireJS, wskazane na http://requirejs.org/docs/api.html#config-shim . Mianowicie: „Nie mieszaj ładowania CDN z konfiguracją podkładek w kompilacji”, gdy używasz optymalizatora.

Szukałem sposobu na użycie tego samego kodu wtyczki jQuery w witrynach z i bez RequireJS. Znalazłem ten fragment dla wtyczek jQuery na https://github.com/umdjs/umd/blob/master/jqueryPlugin.js . Otaczasz swoją wtyczkę tym kodem i będzie działać poprawnie w obu przypadkach.

(function (factory) {
if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module depending on jQuery.
    define(['jquery'], factory);
} else {
    // No AMD. Register plugin with global jQuery object.
    factory(jQuery);
}
}(function ($) {

    $.fn.yourjQueryPlugin = function () {
        // Put your plugin code here
    };  

}));

Kredyt trafia do jrburke; podobnie jak javascript, jego funkcje znajdują się wewnątrz funkcji działających na inne funkcje. Ale myślę, że rozpakowałem, co robi.

Argument funkcji factoryw pierwszym wierszu jest sam w sobie funkcją, która jest wywoływana w celu zdefiniowania wtyczki w $argumencie. Gdy nie ma modułu ładującego zgodnego z AMD, jest on wywoływany bezpośrednio w celu zdefiniowania wtyczki w jQueryobiekcie globalnym . To tak, jak w przypadku wspólnego idiomu definicji wtyczki:

function($)
{
  $.fn.yourjQueryPlugin = function() {
    // Plugin code here
  };
}(jQuery);

Jeśli istnieje moduł ładujący, factoryjest rejestrowany jako wywołanie zwrotne dla modułu ładującego do wywołania po załadowaniu jQuery. Załadowana kopia jQuery jest argumentem. To odpowiednik

define(['jquery'], function($) {
  $.fn.yourjQueryPlugin = function() {
     // Plugin code here
  };
})
Carl Raymond
źródło
3
Podoba mi się ta odpowiedź, ponieważ chociaż pytanie dotyczyło wtyczki jQuery, działa to dla dowolnego modułu lub biblioteki, nie tylko dla jQuery. Zajęło mi chwilę, zanim obejrzałam twój kod, ale kiedy już to zrobiłem, miało to sens.
Adam Tuttle
1
To zdecydowanie nieprzenikniony javascript. Dodałem wyjaśnienie, jak to działa.
Carl Raymond
Jakieś wskazówki, jak to zrobić i stworzyć wtyczkę działającą z jQuery lub Zepto? Mógłbyś łatwo zastąpić kod inny niż AMD factory(jQuery || Zepto);, ale nie wiem, jak zrobiłbyś część AMD. Myślę, że musiałbyś ustawić "ścieżkę" jQuery na zepto? paths: { jquery: 'vendor/zepto/zepto.min' }
Ryan Wheale
wow, od dawna chciałem zrozumieć ten fragment kodu. Bardzo dziękuję, czy shimzasadniczo to nie robi właśnie tego? Chyba nie ... ponieważ powiedziałeś, że ręcznie kodujesz to jak powyżej.
Eugene
Protip dla idiotów takich jak ja: tam, gdzie jest napisane $.fn.jqueryPluginwe fragmencie, zmień jqueryPluginna nazwę wtyczki !!
Matt Lacey,
2

Podobnie jak FYI dla wszystkich niektórych wtyczek jquery, które już używają amd / require, nie musisz niczego deklarować w shim. W rzeczywistości może to w niektórych przypadkach powodować problemy.

Jeśli zajrzysz do pliku JS jquery cookie, zobaczysz zdefiniowane wywołania i require (["jquery"]).

aw jquery.js zobaczysz wywołanie do define ("jquery", [], function () ...

TPEACHES
źródło