So machen Sie ein jQuery-Plugin mit requirejs ladbar

88

Ich arbeite mit requirejs + jquery und habe mich gefragt, ob es eine clevere Möglichkeit gibt, ein jQuery-Plugin mit require gut funktionieren zu lassen.

Zum Beispiel verwende ich jQuery-Cookie. Wenn ich es richtig verstanden habe, kann ich eine Datei namens jquery-cookie.js und inside do erstellen

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

Ich fragte mich, ob ich Dinge wie jQuery tun könnte, was so ist:

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

oder wenn dies die einzige Möglichkeit ist, jQuery-Plugins mit requirejs oder einem amd kompatibel zu machen

Nicola Peluchetti
quelle

Antworten:

67

Sie müssen nur entweder tun

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

am Ende von jquery-cookie.js, OR

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

überall, bevor Sie jquery-cookie einfügen (z. B. überall dort, wo Daten-main darauf verweist).

Der letzte Codeblock, den Sie veröffentlicht haben, eignet sich für Dinge wie jQuery, die neu verteilt werden und sich möglicherweise in einer AMD-Umgebung befinden oder nicht. Idealerweise hätte jedes jQuery-Plugin dies bereits eingerichtet.

Ich bevorzuge es, die enthaltenen Bibliotheken so unverfälscht wie möglich zu halten, daher scheint mir die globale Shim-Konfiguration einmal pro Seite die sauberste Lösung zu sein . Auf diese Weise sind Upgrades sicherer und CDNs werden zu einer Möglichkeit.

Hans
quelle
1
Wenn ich nicht sowohl das Definieren als auch das Shim mache, funktionieren die Dinge nicht, ich bekomme eine $ .cookie ist keine Funktionsfehlermeldung
Nicola Peluchetti
Nach meiner Erfahrung ist es nicht ausreichend, nichts von der Definitionsfunktion zurückzugeben. Requirejs erkennt nicht, dass das Modul geladen ist. Dies kann durch Shim geweckt werden: {Plugins: {hängt ab: ['jquery'], Exporte: 'Plugins'}
Honzajde
Sie sollten beachten, dass das jQuery-Plugin-Skript tatsächlich ausgeführt werden muss. Ich bin kein Experte, aber ich habe eine einfache Lösung gefunden, bei der Sie eine einzige require(['plugin1', 'plugin2']);usw. haben. Es wird kein Rückruf übergeben, sodass nur die Plugin-Skripte selbst ausgeführt werden. Dies bedeutet, dass sie sich dann selbst hinzufügen, jQuery.fnsodass Sie überall "jquery" als Abhängigkeit auflisten können und sie eingeschlossen werden. Wie gesagt, ich bin ziemlich neu in diesem Bereich und es gibt möglicherweise einen besseren Ansatz (z. B. nur die Verwendung eines scriptTags), aber das funktioniert.
Joshua Bambrick
3
Josh: Sie spielen darauf, dass alles in der richtigen Reihenfolge geladen wird. Einige Benutzer auf Ihrer Website sehen wahrscheinlich defekte Inhalte. Das Problem ist nicht so sehr, dass das Plugin geladen wird, sondern wann das Plugin geladen wird und was zu diesem Zeitpunkt noch ausgeführt wird. Der Hauptgrund für die Verwendung von require besteht darin, eine sinnvolle Reihenfolge der Operationen sicherzustellen, die auf Abhängigkeiten und nicht auf Vermutungen basiert.
Hans
104

Bei der Verwendung der Shim-Konfiguration in RequireJS gibt es einige Einschränkungen, auf die unter http://requirejs.org/docs/api.html#config-shim hingewiesen wird . "Mischen Sie das CDN-Laden nicht mit der Shim-Konfiguration in einem Build", wenn Sie den Optimierer verwenden.

Ich suchte nach einer Möglichkeit, denselben jQuery-Plugin-Code auf Websites mit und ohne RequireJS zu verwenden. Ich habe dieses Snippet für jQuery-Plugins unter https://github.com/umdjs/umd/blob/master/jqueryPlugin.js gefunden . Sie wickeln Ihr Plugin in diesen Code ein und es wird in beiden Fällen ordnungsgemäß funktionieren.

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

}));

Kredit geht an jrburke; Wie so viel Javascript sind es Funktionen innerhalb von Funktionen, die auf andere Funktionen einwirken. Aber ich glaube, ich habe ausgepackt, was es tut.

Das Funktionsargument factoryin der ersten Zeile ist selbst eine Funktion, die aufgerufen wird, um das Plugin für das $Argument zu definieren . Wenn kein AMD-kompatibler Loader vorhanden ist, wird er direkt aufgerufen, um das Plugin für das globale jQueryObjekt zu definieren . Das ist genau wie die gängige Plugin-Definitionssprache:

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

Wenn ein Modullader vorhanden ist, factorywird dieser als Rückruf für den Loader registriert, der nach dem Laden von jQuery aufgerufen werden soll. Die geladene Kopie von jQuery ist das Argument. Es ist gleichbedeutend mit

define(['jquery'], function($) {
  $.fn.yourjQueryPlugin = function() {
     // Plugin code here
  };
})
Carl Raymond
quelle
3
Ich mag diese Antwort, denn obwohl es sich um ein jQuery-Plugin handelte, funktioniert dies für jede Art von Modul oder Bibliothek, nicht nur für jQuery. Ich brauchte eine Minute, um meinen Kopf um Ihren Code zu wickeln, aber als ich das tat, machte es vollkommen Sinn.
Adam Tuttle
1
Es ist definitiv undurchdringliches Javascript. Ich habe eine Erklärung hinzugefügt, wie es funktioniert.
Carl Raymond
Gibt es Tipps dazu und ein Plugin, das mit jQuery oder Zepto funktioniert? Sie könnten den Nicht-AMD-Code leicht durch einen ersetzen factory(jQuery || Zepto);, aber ich weiß nicht, wie Sie den AMD-Teil ausführen würden. Ich denke, Sie müssten den jQuery "Pfad" auf zepto setzen? paths: { jquery: 'vendor/zepto/zepto.min' }
Ryan Wheale
Wow, ich wollte schon lange diesen Codeausschnitt verstehen. Vielen Dank. shimTut das nicht im Wesentlichen genau das? Ich denke nicht ... weil Sie sagten, dass Sie es manuell wie oben codieren.
Eugene
Protip für Idioten wie mich: Wo $.fn.jqueryPluginim Snippet steht, ändere jqueryPluginden Plugin-Namen !!
Matt Lacey
2

Genau wie zu Ihrer Information verwenden einige der JQuery-Plugins bereits amd / require, sodass Sie nichts im Shim deklarieren müssen. In der Tat kann dies in einigen Fällen zu Problemen für Sie führen.

Wenn Sie in das jquery-Cookie JS schauen, sehen Sie, wie Aufrufe definiert und erforderlich sind (["jquery"]).

und in jquery.js sehen Sie einen Aufruf zum Definieren ("jquery", [], function () ...

TPEACHES
quelle