Da die Codelogik von js immer schwerer wird, kann eine js-Datei Tausende von Zeilen enthalten, was für Entwicklung und Wartung sehr ungünstig ist. Kürzlich teile ich das logiklastige JS in Module auf. Als ich mich mit der Frage herumschlug, ob ich requirejs oder seajs verwenden sollte, habe ich schließlich requirejs vorgezogen. Schließlich sind offizielle Dokumente professioneller...
Selbst mit vollständiger offizieller Dokumentation stoßen wir jedoch immer noch auf viele Probleme, beispielsweise bei der Verwendung von jquery-ui.
Im Folgenden finden Sie eine Schritt-für-Schritt-Erklärung der aufgetretenen Probleme und der Lösungen.
Verständnis von AMD und CMD
Ein typisches Beispiel für AMD (asynchrone Moduldefinition) ist requirejs, während ein typisches Beispiel für CMD (gemeinsame Moduldefinition) Taobaos Seajs sind.
Was ihnen gemeinsam ist, ist, dass sie beide js asynchron laden. Der Unterschied besteht jedoch darin, dass require.js sofort nach dem Laden ausgeführt wird, während seajs erst ausgeführt wird, wenn es in die Hauptfunktion eintritt und ausgeführt werden muss.
Wenn Sie Seajs verwenden, ist die anfängliche Lade- und Ausführungseffizienz höher, aber js kann während der Verwendung abgerufen und ausgeführt werden, sodass Verzögerungen auftreten und die Benutzererfahrung beeinträchtigen können (ich habe es nicht ausprobiert. Wenn ich mich also irre, Seien Sie nicht überrascht). Und requirejs führt zu Beginn alle geladenen js aus. Wenn Ihr Modul zu diesem Zeitpunkt einige Ausführungsmethoden enthält, werden diese möglicherweise nicht in der gewünschten Reihenfolge ausgeführt.
Wenn Sie also an asynchrone Programmierung gewöhnt sind und eine vollständige Dokumentation wünschen, wird die Verwendung von requirejs empfohlen. Wenn Sie spezielle Anforderungen an die Ausführungsreihenfolge haben und die Entwicklung erleichtern möchten, können Sie auch Seajs verwenden.
So lösen Sie das Problem der zirkulären Abhängigkeit in requirejs
Wenn ein von Ihnen definiertes Modul a Modul b verwendet und Modul b Modul a verwendet, wird eine zirkuläre Abhängigkeitsausnahme ausgelöst.
Zum Beispiel habe ich hier ein Beispiel für eine zirkuläre Abhängigkeit geschrieben.
Hauptseite:
<!DOCTYPE html> <html> <head> </head> <body> <script data-main="test.js" src="lib/require.js"></script> </body> </html>
Hauptmethode:
requirejs.config({ baseUrl: './' }); requirejs(['js/a'],function (a){ console.log("in test"); a.testfromb(); });
Im a.js-Modul stellt die Methode test() die Methode zum Aufrufen von b bereit, und die Methode testfromb() ruft die Methode von b auf
define(function(require){ var b = require("js/b"); console.log("in a"); return { atest:function(){ console.log("test in a"); }, testfromb:function(){ console.log("testfromb in a"); b.btest(); } } });
In Modul b wird die Methode von a aufgerufen.
define(function(require){ var a = require("js/a"); console.log("in b"); return { btest:function(){ console.log("test in b"); a.atest(); } } });
Dies entspricht dem Aufruf der Methode von b, die Methode von b hängt jedoch von der Methode von a ab, wodurch eine zirkuläre Abhängigkeit entsteht. Der Browser meldet einen Fehler:
Unabgefangener Fehler: Modulname „js/a“ wurde noch nicht für Kontext geladen: _
Laut offizieller Dokumentation handelt es sich hierbei um ein Designproblem, das so weit wie möglich vermieden werden sollte. Was sollten Sie also tun, wenn Sie es nicht vermeiden können? Modul b kann wie folgt geändert werden:
define(function(require){ // var a = require("js/a"); console.log("in b"); return { btest:function(){ console.log("test in b"); require("js/a").atest(); } } });
Hier ist zu warten, bis die test()-Methode ausgeführt wird, bevor das Modul geladen wird. Zu diesem Zeitpunkt wurde offensichtlich Modul a geladen. Sie können die Ausgabeinformationen sehen:
in b a.js:3 in a test.js:6 in test a.js:9 testfromb in a b.js:6 test in b a.js:6 test in a
Auf die gleiche Weise funktioniert es möglicherweise nicht, wenn Sie a ändern. Dies liegt daran, dass die Reihenfolge des Modulladens bei b beginnt.
Den Quellcode für zirkuläre Abhängigkeiten finden Sie auf der Cloud-Festplatte
So verwenden Sie JQuery in RequireJS
Wenn Sie jquery relativ einfach verwenden möchten, fügen Sie einfach die entsprechenden Abhängigkeiten direkt zu main.js hinzu:
requirejs.config({ baseUrl: './', paths:{ 'jquery':'lib/jquery' } }); requirejs(['jquery'], function ($){ $('#test').html('test'); });
如何在requirejs中使用jquery插件 对于jquery的插件,比较常见的做法都是传入一个jquery的对象,在这个jquery对象的基础上添加插件对应的方法。 首先需要添加jquery插件的依赖,这里用两个插件举例子——jquery-ui和jquery-datatables
requirejs.config({ baseUrl: './', paths:{ 'jquery':'lib/jquery', 'jquery-ui':'lib/jquery-ui', 'jquery-dataTables':'lib/jquery.dataTables' }, shim:{ 'jquery-ui':['jquery'], 'jquery-dataTables':['jquery'] } }); requirejs(['jquery','jquery-ui','jquery-dataTables'], function ($){ .... });
由于jquery插件都需要依赖于jquery,因此可以在shim中指定依赖关系。 除了上面这种使用方法,也可以使用commonJS风格的调用:
define(function(require){ var $ = require('jquery'); require('jquery-ui'); require('jquery-dataTables'); //下面都是测试,可以忽略 var _test = $('#test'); _test.selectmenu({ width : 180, change : function(event, ui) { console.log('change'); } }); return { test:function(){ //测试jquery-ui _test.append($('<option>test1</option><option>test1</option>')); _test.selectmenu("refresh"); //测试jquery-datatables var _table = $('table'); _table.dataTable(); } } });
Bei der Ausführung des obigen Codes wird jedoch eine Ausnahme gemeldet:
Unabgefangener TypeError: _table.dataTable ist keine Funktion
Dies liegt daran, dass dataTables kein Modul im Require-Stil ist. Wenn es also direkt auf diese Weise eingeführt wird, werden seine internen anonymen Funktionen nicht ausgeführt. Sie können seine anonyme Funktion ändern, indem Sie das $-Objekt in der letzten Zeile übergeben:
*/ return $.fn.dataTable; //}));原来是这样 }($)));//这里增加执行这个匿名函数,并且传入$对象。 }(window, document));
Dies ist auch eine Methode zur Suche im Internet, das Prinzip beruht jedoch auf mangelnder Erfahrung....
Sie können den Beispielcode auf der Cloud-Festplatte nachlesen. Da die importierten Ressourcen nicht vollständig sind, wird ein Fehler gemeldet und kann ignoriert werden. Denn die Ausführung des UI-Plug-Ins bedeutet, dass es erfolgreich war.
Probleme bei der Verwendung von jquery-ui mit requirejs
Da requirejs unmittelbar nach dem Laden der js-Datei ausgeführt wird, kann es dazu führen, dass die Ereignisse der Seite fehlschlagen, wenn Ihr JQuery-UI-Plug-in die DOM-Seite aktualisieren muss.
Nachdem Ihr Modul beispielsweise geladen wurde, ist ein Klickereignis an ein bestimmtes Element $('#test') auf der Seite gebunden. Wenn jedoch ein bestimmtes UI-Plug-In verwendet wird, rendert das Plug-In das DOM-Element erneut und das dem Test entsprechende Klickereignis wird ungültig.
Lösung:
•Verzögern Sie die Ereignisbindung, bis das DOM-Element gerendert ist, und lösen Sie dann die Bindung manuell aus
•Ereigniserfassung kann auch anstelle der Ereignisbindung von DOM-Elementen verwendet werden (zu mühsam...nicht empfohlen).
require("xxx").initEvents(); Häufige Szenarien:
Zum Beispiel verwende ich das jquery-steps-UI-Plug-in auf der Seite, das die Seite neu rendert. Dies führte dazu, dass die Ereignisse, die ich ursprünglich gebunden hatte, ungültig wurden. Ich konnte die Bindung nur verschieben, bis die js-Seite wiederhergestellt war, und dann erneut binden.
Der obige Artikel - Modulare Programmierung basierend auf RequireJS und JQuery - Umfassende Analyse häufig gestellter Fragen - ist der gesamte vom Herausgeber geteilte Inhalt. Ich hoffe, dass er Ihnen eine Referenz geben kann, und ich hoffe, dass Sie Script Home unterstützen.