Come rendere un plugin jQuery caricabile con requirejs


88

Sto lavorando con requirejs + jquery e mi chiedevo se ci fosse un modo intelligente per far funzionare bene un plugin jQuery con require.

Ad esempio sto usando jQuery-cookie. Se ho capito bene posso creare un file chiamato jquery-cookie.js e all'interno do

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"]
    }
} );

mi chiedevo se potevo fare cose come fa jQuery, che è così:

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

o se questo è l'unico modo per rendere i plugin jQuery compatibili con requirejs o qualsiasi amd

Risposte:


67

Hai solo bisogno di fare ENTRAMBI

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

alla fine di jquery-cookie.js, OR

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

ovunque prima di includere jquery-cookie (come dove punta data-main, ad esempio).

L'ultimo blocco di codice che hai pubblicato è utile per cose come jQuery che vengono ridistribuite e possono essere o meno in un ambiente AMD. Idealmente ogni plug-in jQuery dovrebbe già averlo configurato.

Preferisco mantenere le librerie incluse il più genuini possibile, quindi la configurazione shim globale una volta per pagina mi sembra la soluzione più pulita . In questo modo gli aggiornamenti sono più sicuri e le CDN diventano una possibilità.


1
Se non eseguo sia la definizione che lo shim, le cose non funzionano, ottengo un $ .cookie non è un messaggio di errore di funzione
Nicola Peluchetti

Per mia esperienza, non restituire nulla dalla funzione di definizione non è sufficiente, requirejs non riconoscerà che il modulo è stato caricato. Questo può essere risolto da shim: {plugins: {dipende: ['jquery'], export: 'plugins'}
honzajde

Dovresti notare che lo script del plugin jQuery deve essere effettivamente eseguito. Non sono un esperto, ma ho trovato una soluzione semplice per cui hai un singolo require(['plugin1', 'plugin2']);ecc. Non viene passato alcun callback, quindi non verrà eseguito nulla tranne gli script del plugin stessi. Ciò significa che si aggiungeranno a se stessi, jQuery.fnquindi ovunque tu possa semplicemente elencare "jquery" come dipendenza e saranno inclusi. Come ho detto, sono abbastanza nuovo in questo e potrebbe esserci un approccio migliore (come usare solo un scripttag) ma funziona.
Joshua Bambrick,

3
Josh: Stai scommettendo che tutto si caricherà nell'ordine giusto. È probabile che alcuni utenti del tuo sito vedano cose non funzionanti. Il problema non è tanto che il plug-in viene caricato, è quando il plug-in viene caricato e cos'altro viene eseguito in quel momento. Il motivo principale per utilizzare require è garantire un ordine ragionevole delle operazioni basato sulle dipendenze piuttosto che su supposizioni.
Hans

104

Ci sono alcuni avvertimenti sull'utilizzo della configurazione shim in RequireJS, indicati su http://requirejs.org/docs/api.html#config-shim . Vale a dire, "Non mischiare il caricamento CDN con la configurazione shim in una build" quando utilizzi l'ottimizzatore.

Stavo cercando un modo per utilizzare lo stesso codice plugin jQuery su siti con e senza RequireJS. Ho trovato questo snippet per i plugin jQuery su https://github.com/umdjs/umd/blob/master/jqueryPlugin.js . Inserisci il tuo plugin in questo codice e funzionerà correttamente in entrambi i casi.

(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
    };  

}));

Il merito va a jrburke; come molto javascript, le sue funzioni all'interno di funzioni che agiscono su altre funzioni. Ma penso di aver disimballato cosa sta facendo.

L'argomento della funzione factorynella prima riga è esso stesso una funzione che viene invocata per definire il plugin $sull'argomento. Quando non è presente alcun caricatore compatibile con AMD, viene richiamato direttamente per definire il plug-in jQuerysull'oggetto globale . È proprio come l'idioma comune della definizione di plugin:

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

Se è presente un caricatore di moduli, factoryviene registrato come callback per il caricatore da richiamare dopo aver caricato jQuery. La copia caricata di jQuery è l'argomento. È equivalente a

define(['jquery'], function($) {
  $.fn.yourjQueryPlugin = function() {
     // Plugin code here
  };
})

3
Mi piace questa risposta perché anche se la domanda riguardava un plugin jQuery, funziona per qualsiasi tipo di modulo o libreria, non solo jQuery. Mi ci è voluto un minuto per capire il tuo codice, ma una volta fatto, aveva perfettamente senso.
Adam Tuttle

1
È decisamente javascript impenetrabile. Ho aggiunto alcune spiegazioni su come funziona.
Carl Raymond

Qualche consiglio su come farlo e creare un plugin che funzioni con jQuery o Zepto? Potresti facilmente sostituire il codice non AMD con factory(jQuery || Zepto);, ma non so come faresti la parte AMD. Penso che dovresti impostare il "percorso" jQuery su zepto ?? paths: { jquery: 'vendor/zepto/zepto.min' }
Ryan Wheale

wow, volevo da tempo capire questo frammento di codice. Grazie mille, shimessenzialmente non è proprio questo? Immagino di no .. perché hai detto che lo stai codificando manualmente come sopra.
eugene

Protip per idioti come me: dove si dice $.fn.jqueryPluginnello snippet, cambia jqueryPluginnel nome del plugin !!
Matt Lacey

2

Proprio come per tua informazione, tutti alcuni plugin jquery usano già amd / require, quindi non è necessario dichiarare nulla nello shim. In effetti, ciò potrebbe causare problemi in alcuni casi.

Se guardi nel cookie jquery JS vedrai define calls e require (["jquery"]).

e in jquery.js vedrai una chiamata a define ("jquery", [], function () ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.