Hinweis: Wenn globalModule für Seajs initialisiert wird (wenn sea.js eingeführt wird), ist die Instanz des Moduls var globalModule = new Module(util.pageUri, STATUS.COMPILED)
Zu diesem Zeitpunkt ids -> ['./a','jquery'], callback -> function(a,$){var num = a.a;$('#J_A').text(num); 🎜 >
Als nächstes wird
Da nach dem Aufruf der _load-Methode zwei Rückruffunktionen erscheinen, markieren wir function(a,$){var num = a.a;$('#J_A').text(num);} als callback1,
wird als nächstes ausgeführt.
Code kopieren Der Code lautet wie folgt:
// Die Methode _load() bestimmt hauptsächlich, welche Ressourcendateien noch nicht bereit sind. Wenn sich alle Ressourcendateien im Bereitschaftszustand befinden, wird Callback2
ausgeführt.
// In diesem Prozess werden auch zirkuläre Abhängigkeiten beurteilt und entladene js werden geladen
Module.prototype._load = function(uris, callback2) {
//util.filter: Lassen Sie alle Datenmitglieder gleichzeitig eine bestimmte Funktion ausführen und ein neues Array zurückgeben. Dies ist das Mitglied, das true zurückgibt, nachdem das ursprüngliche Array-Mitglied den Rückruf ausgeführt hat
//unLoadedUris ist das Modul-URI-Array, das nicht kompiliert wurde
var unLoadedUris = util.filter(uris, function(uri) {
//Gibt das Mitglied zurück, dessen boolescher Wert der Ausführungsfunktion „true“ ist, wenn die URI in der internen Variablen „cacheModules“ vorhanden und nicht vorhanden ist oder ihr Statuswert in den gespeicherten Informationen kleiner als STATUS.READY
ist
// Der Wert von STATUS.READY ist 4. Wenn er kleiner als vier ist, besteht die Möglichkeit, dass er abgerufen oder heruntergeladen wird.
Rückgabe-URI && (!cachedModules[uri] ||
zwischengespeicherteModule[uri].status
});
//Wenn alle Module in URIS bereit sind, führen Sie den Rückruf aus und verlassen Sie den Funktionskörper (zu diesem Zeitpunkt wird die _compile-Methode des Moduls aufgerufen).
var length = unLoadedUris.length
if (length === 0) { callback2() return }
//Die Anzahl der Module, die noch nicht geladen wurden
var bleibt = Länge
//Erstellen Sie einen Abschluss und versuchen Sie, nicht geladene Module zu laden
für (var i = 0; i < Länge; i ) {
(Funktion(uri) {
//Stellen Sie fest, ob die Speicherinformationen der URI in der internen Variablen zwischengespeicherteModule nicht vorhanden sind, und instanziieren Sie ein Modulobjekt
var module =cachedModules[uri] ||
(cachedModules[uri] = neues Modul(uri, STATUS.FETCHING))
//Wenn der Statuswert des Moduls größer oder gleich 2 ist, bedeutet dies, dass das Modul heruntergeladen wurde und bereits lokal vorhanden ist. Zu diesem Zeitpunkt wird onFetched()
ausgeführt
// Andernfalls rufen Sie fetch(uri, onFetched) auf und versuchen Sie, die Ressourcendatei herunterzuladen. Nachdem die Ressourcendatei heruntergeladen wurde, wird Onload ausgelöst und die Rückrufmethode onFetched wird in Onload ausgeführt.
module.status >= STATUS.FETCHED ? onFetched() : fetch(uri, onFetched)
Funktion onFetched() {
module =cachedModules[uri]
//Wenn der Statuswert des Moduls größer oder gleich STATUS.SAVED ist, bedeutet dies, dass alle Abhängigkeitsinformationen des Moduls abgerufen wurden
if (module.status >= STATUS.SAVED) {
//getPureDependencies: Abhängigkeitsarray ohne zirkuläre Abhängigkeiten abrufen
var deps = getPureDependencies(module)
//Wenn das Abhängigkeitsarray nicht leer ist
if (deps.length) {
//Führen Sie die Methode _load() erneut aus, bis alle Abhängigkeiten geladen sind und der Rückruf ausgeführt wird
Module.prototype._load(deps, function() {
cb(Modul)
})
}
//Wenn das Abhängigkeitsarray leer ist, führen Sie cb(module)
direkt aus
sonst {
cb(Modul)
}
}
// Wenn die Erfassung fehlschlägt, z. B. 404 oder nicht der modularen Spezifikation entspricht
//In diesem Fall bleibt module.status bei FETCHING oder FETCHED
sonst {
cb()
}
}
})(unLoadedUris[i])
}
// cb-Methode – Rückruf wird nach dem Laden aller Module
ausgeführt
Funktion cb(module) {
// Wenn die Speicherinformationen des Moduls vorhanden sind, ändern Sie den Statuswert in seinen Modulspeicherinformationen in STATUS.READY
Modul && (module.status = STATUS.READY)
// Den Rückruf nur ausführen, wenn alle Module geladen sind.
--remain === 0 && callback2()
}
}
}
Die Array-Länge von unLoadedUris beträgt hier 2, ['http://localhost/test/SEAJS/a.js','http://localhost/test/SEAJS/lib/juqery/1.7.2/juqery- debug .js'], sodass als nächstes zwei mit js-Pfaden benannte Abschlüsse generiert werden.
Nehmen Sie http://localhost/test/SEAJS/a.js als Beispiel
Als nächstes: Zunächst wird ein Modul erstellt:
CachedModules('http://localhost/test/SEAJS/a.js') = neues Modul('http://localhost/test/SEAJS/a.js',1)
module.status >= STATUS.FETCHED ? onFetched() : fetch(uri, onFetched)
Da Modul a zu diesem Zeitpunkt nicht geladen ist, wird als nächstes fetch(uri, onFetched) ausgeführt, also fetch('http://localhost/test/SEAJS/a.js', onFetched).
Funktion fetch(uri, onFetched) {
// Ersetzen Sie die URI durch die neue Anforderungsadresse gemäß den Regeln in der Karte
var requestUri = util.parseMap(uri)
// Überprüfen Sie zunächst, ob in der erhaltenen Liste
ein requestUri-Datensatz vorhanden ist
If (fetchedList[requestUri]) {
// Aktualisieren Sie zu diesem Zeitpunkt die Modulspeicherinformationen der ursprünglichen URI auf die durch Map
neu definierte requestUri
zwischengespeicherteModule[uri] = zwischengespeicherteModule[requestUri]
// OnFetched ausführen und zurückgeben, was bedeutet, dass das Modul erfolgreich abgerufen wurde
onFetched()
zurück
}
//Fragen Sie die Speicherinformationen von requestUri in der Erfassungsliste ab
If (fetchingList[requestUri]) {
// Fügen Sie den Rückruf hinzu, der der URL in der Rückrufliste entspricht, und geben Sie
zurück
CallbackList[requestUri].push(onFetched) //Wenn es abgerufen wird, schieben Sie die onFetched-Rückrufmethode dieses Moduls in das Array und kehren Sie zurück.
zurück
}
// Wenn das Modul, das Sie abrufen möchten, nicht in fetchedList und fetchingList erscheint, fügen Sie seine Informationen in die Anforderungsliste bzw. Rückrufliste ein
fetchingList[requestUri] = true
callbackList[requestUri] = [onFetched]
// Holt es
Module._fetch(
requestUri,
function() {
fetchedList[requestUri] = true
// Aktualisiert den Modulstatus
// Wenn module.status gleich STATUS.FECTCHING ist, ändern Sie den Modulstatus in FETCHED
var module =cachedModules[uri]
If (module.status === STATUS.FETCHING) {
module.status = STATUS.FETCHED
}
if (fetchingList[requestUri]) {
fetchingList[requestUri] löschen
}
// Aufrufe callbackList Einheitliche Ausführung von Callbacks
if (callbackList[requestUri]) {
util.forEach(callbackList[requestUri], function(fn) {
Fn () // fn ist die aufgerufene Methode, die Modul A entspricht.
})
callbackList[requestUri] löschen
}
},
config.charset
)
}
Als nächstes wird Module._fetch() ausgeführt. Die Callback-Funktion heißt hier callback3.
Diese Methode dient dazu, die Methode „loadJs“ aufzurufen, um eine.js-Datei dynamisch herunterzuladen. (Da es eine und jquery gibt, werden hier zwei neue Skripte erstellt.) Wenn Sie ein Skript erstellen und es dem Kopf hinzufügen, wird dies in seajs nicht der Fall sein heruntergeladen, wartet aber auf jquery. Das Skript wird erst heruntergeladen, wenn es erstellt und dem Head hinzugefügt wurde (der Google-Debugger setzt einen Haltepunkt und zeigt immer „Ausstehend“ an). Warum ist das so?
(Es wird empfohlen, hier zu lesen: http://ux.sohu.com/topics/50972d9ae7de3e752e0081ff. Hier werde ich über zusätzliche Probleme sprechen. Sie wissen vielleicht, warum wir weniger Tabellen für das Layout verwenden sollten, weil Tabelle Beim Rendern des Baums sind mehrere Berechnungen erforderlich, während div nur eine benötigt. Gleichzeitig sagte mir der Midea-E-Commerce-Interviewer, dass die Tabelle vollständig analysiert werden muss, bevor sie angezeigt wird werden so oft angezeigt, wie sie analysiert werden. Daher werden in IE6, 7 und 8, wenn Sie innerHTML zum Erstellen einer „
“ verwenden,
;tbody>< wird automatisch hinzugefügt.
Nachdem der Download erfolgreich war, wird er analysiert und ausgeführt und die Definitionsmethode wird ausgeführt. Der Code von Modul a wird zuerst ausgeführt.
define(id,deps,function(){}) Methodenanalyse
//Definition definieren, id: Modul-ID, deps: Modulabhängigkeit, Fabrik
Module._define = function(id, deps, Factory) {
//Abhängigkeiten auflösen //Wenn deps kein Array-Typ und Factory eine Funktion ist
if (!util.isArray(deps) && util.isFunction(factory)) { // Gleicht regelmäßig die erforderliche Zeichenfolge im Funktionskörper ab und bildet ein Array zur Rückgabe und weist den Wert deps
zu
deps = util.parseDependencies(factory.toString())
}
//Metainformationen festlegen
var meta = { id: id, dependencies: deps, Factory: Factory }
if (document.attachEvent) {
// Den Knoten des aktuellen Skripts abrufen
var script = util.getCurrentScript()
// Wenn der Skriptknoten vorhanden ist
if (Skript) {
// Holen Sie sich die ursprüngliche URI-Adresse
derivativeUri = util.unParseMap(util.getScriptAbsoluteSrc(script)) }
if (!derivedUri) {
util.log('Fehler beim Ableiten des URI vom interaktiven Skript für:', Factory.toString(), 'warn')
}
}
.........
}
define führt zunächst eine Beurteilung der Factory durch, um festzustellen, ob es sich um eine Funktion handelt (der Grund dafür ist, dass define auch Dateien und Objekte umfassen kann)
Wenn es sich um eine Funktion handelt, wird die Funktion über Factory.toString() abgerufen, und die Abhängigkeit von a.js wird durch regulären Abgleich abgerufen und die Abhängigkeit wird in Deps
gespeichert
Für a.js ist die Abhängigkeit b.js, also ist deps ['./b']
Und speichern Sie die Informationen von a.js var meta = { id: id, dependencies: deps, Factory: Factory }
Für a.js meta = { id : undefiniert , Abhängigkeiten : ['./b'] , Fabrik : function(xxx){xxx}}
Im IE 6-9-Browser können Sie den Pfad des aktuell ausgeführten js abrufen. Im Standardbrowser ist dies jedoch nicht möglich, also weisen Sie die Metainformationen vorübergehend anonymModuleMeta = meta zu.
Dann wird Onload ausgelöst und die Rückrufmethode callback3 aufgerufen. Diese Rückrufmethode ändert den Statuswert des aktuellen Rückrufmoduls (a.js) und setzt ihn auf module.status = STATUS.FETCHED.
Als nächstes wird der Rückruf, der a.js in der Rückrufwarteschlange callbackList entspricht, einheitlich ausgeführt, nämlich onFetched.
Die onFetched-Methode prüft, ob Modul a abhängige Module hat. Da a von b abhängt, wird _load() auf b.js ausgeführt, von dem Modul a abhängt.
lädt das b-Modul herunter und führt dann zuerst die Methode define von jquery aus. Da JQuery nach dem Onload-Rückruf nicht von Modulen abhängt. onFetched ruft die cb-Methode auf.
Wenn b nach dem gleichen Prozess wie a implementiert wird, wird das c-Modul heruntergeladen. Schließlich werden alle Module c, b und a heruntergeladen und definiert, und nach Abschluss des Onloads wird auch die cb-Methode aufgerufen (zuerst c, dann b, dann c)
Nachdem alle Module bereit sind, wird die Methode callback2 aufgerufen.
Rufen Sie abschließend Callback2 auf und führen Sie die _compile-Methode der Module a und jquery aus:
Kompilieren Sie zuerst das a.js-Modul und die Funktion von Modul a wird ausgeführt. Da a require(b.js) enthält, wird die Funktion von Modul b ausgeführt.
Die Funktion von Modul a beginnt mit der Ausführung von
Die Funktion von Modul b beginnt mit der Ausführung von
Die Funktion von Modul c beginnt mit der Ausführung von
Die Funktion von Modul c wird ausgeführt
Die Funktion von Modul b wird ausgeführt
Die Funktion von Modul a wird ausgeführt
Führen Sie abschließend die JQuery-Funktion aus.
Nachdem die Kompilierung abgeschlossen ist, wird callback1 ausgeführt und es können a- und jquery-Objekte verwendet werden.
PS: Die SeaJS-Version wurde aktualisiert und es gibt jetzt keine _compile-Methode. (Jeder schaut es sich selbst an, ich will es mir auch ansehen)
Dann lasst uns über den Modul-Compilation_Compile-Prozess von SeaJs sprechen.
Das erste ist die Kompilierung von a.js
Module.prototype._compile = function() {
126 var module = this
127 // Wenn das Modul kompiliert wurde, geben Sie module.exports
direkt zurück
128 if (module.status === STATUS.COMPILED) {
129 return module.exports
130 }
133 // 1. Die Moduldatei ist 404.
134 // 2. Die Moduldatei ist nicht im gültigen Modulformat geschrieben.
135 // 3. andere Fehlerfälle.
136 //Hier geht es darum, einige abnormale Situationen zu behandeln und null direkt zurückzugeben
137 if (module.status < STATUS.SAVED && !hasModifiers(module)) {
138 gibt null zurück
139 }
140 // Ändern Sie den Modulstatus in COMPILING, was darauf hinweist, dass das Modul kompiliert wird
141 module.status = STATUS.COMPILING
142
143 // Wird intern vom Modul verwendet und ist eine Methode, mit der die von anderen Modulen (sogenannten Submodule) bereitgestellten Schnittstellen abgerufen und synchrone Vorgänge ausgeführt werden
144 Funktion require(id) {
145 // Den Pfad des Moduls anhand der ID
analysieren
146 var uri =solve(id, module.uri)
147//Holen Sie sich das Modul aus dem Modulcache (beachten Sie, dass das Submodul hier tatsächlich als Abhängigkeit des Hauptmoduls heruntergeladen wurde)
148 var child =cachedModules[uri]
149
150//Gib einfach null zurück, wenn uri ungültig ist.
151//Wenn das untergeordnete Element leer ist, kann dies nur bedeuten, dass die Parameterfüllung falsch ist und die URL falsch ist. Dann wird direkt null zurückgegeben
152 if (!child) {
153 gibt null zurück
154 }
155
156 // Vermeidet zirkuläre Anrufe.
157//Wenn der Status des Submoduls STATUS.COMPILING ist, geben Sie child.exports direkt zurück, um ein wiederholtes Kompilieren des Moduls aufgrund zirkulärer Abhängigkeiten zu vermeiden
158 if (child.status === STATUS.COMPILING) {
159 return child.exports
160 }
161//Zeigt auf das Modul, das während der Initialisierung das aktuelle Modul aufruft. Gemäß diesem Attribut kann der Aufrufstapel während der Modulinitialisierung abgerufen werden.
162 child.parent = Modul
163//Gib das kompilierte untergeordnete Modul zurück.exports
164 return child._compile()
165 }
166 // Wird intern vom Modul verwendet, um das Modul asynchron zu laden und den angegebenen Rückruf auszuführen, nachdem der Ladevorgang abgeschlossen ist.
167 require.async = function(ids, callback) {
168 module._use(ids, callback)
169 }
170 // Verwenden Sie den Pfadanalysemechanismus innerhalb des Modulsystems, um den Modulpfad zu analysieren und zurückzugeben. Diese Funktion lädt das Modul nicht und gibt nur den aufgelösten absoluten Pfad zurück.
171 require.resolve = function(id) {
172 return discover(id, module.uri)
173 }
174 // Über dieses Attribut können Sie alle vom Modulsystem geladenen Module anzeigen.
175 // Wenn Sie in einigen Fällen ein Modul neu laden müssen, können Sie die URL des Moduls abrufen und dann seine Informationen löschen, indem Sie require.cache[uri] löschen. Auf diese Weise erhalten Sie es bei der nächsten Verwendung wieder.
176 require.cache = zwischengespeicherteModule
177
178 // require ist eine Methode, mit der die von anderen Modulen bereitgestellten Schnittstellen abgerufen werden.
179 module.require = require
180 // Exports ist ein Objekt, mit dem Modulschnittstellen zur Außenwelt bereitgestellt werden.
181 module.exports = {}
182 var Factory = module.factory
183
184 // Wenn Factory eine Funktion ist, stellt sie die Konstruktionsmethode des Moduls dar. Durch Ausführen dieser Methode können Sie die vom Modul bereitgestellte Schnittstelle abrufen.
185 if (util.isFunction(factory)) {
186 compileStack.push(module)
187 runInModuleContext(factory, module)
188 compileStack.pop()
189 }
190 // Wenn Factory ein Nicht-Funktionstyp wie Objekt oder String ist, bedeutet dies, dass die Schnittstelle des Moduls das Objekt, der String oder andere Werte ist.
191 // Wie zum Beispiel: define({ "foo": "bar" });
192 // Zum Beispiel: define('Ich bin eine Vorlage. Mein Name ist {{name}}.');
193 else if (factory !== undefiniert) {
194 module.exports = Fabrik
195 }
196
197 // Ändern Sie den Modulstatus in COMPILED, was anzeigt, dass das Modul kompiliert wurde
198 module.status = STATUS.COMPILED
199 // Modulschnittstellenänderung über seajs.modify()
ausführen
200 execModifiers(module)
201 return module.exports
202 }
if (util.isFunction(factory)) {
186 compileStack.push(module)
187 runInModuleContext(factory, module)
188 compileStack.pop()
189 }
Hier wird module.export initialisiert. runInModuleContext-Methode:
// Modulcode gemäß Modulkontext ausführen
489 Funktion runInModuleContext(fn, module) {
490 // Übergeben Sie die beiden Parameter, die sich auf das Modul und das Modul selbst beziehen
491 // Exporte werden zum Offenlegen von Schnittstellen verwendet
492 // require wird verwendet, um abhängige Module zu erhalten (Synchronisation) (Kompilierung)
493 var ret = fn(module.require, module.exports, module)
494 // Unterstützt das Rückgabewert-Expositionsschnittstellenformular, z. B.:
495 // zurück {
496 // fn1 : xx
497 // ,fn2: xx
498 // ...
499 // }
500 if (ret !== undefiniert) {
501 module.exports = ret
502 }
503 }
Führen Sie die Funktionsmethode in a.js aus, dann wird var b = require("b.js"),
aufgerufen
Die Anforderungsmethode gibt den Rückgabewert der Kompilierungsmethode von b zurück, und im b-Modul befindet sich var c = require('c.js').
Zu diesem Zeitpunkt wird die Kompilierungsmethode von c aufgerufen, und dann wird die Funktion von c aufgerufen. Wenn in c das Objekt verfügbar gemacht werden soll oder das Objekt c zurückgegeben wird, sind die Exporte des Moduls c = c. Oder direkt module.export = c; kurz gesagt, module c.export = c wird am Ende zurückgegeben, also var c = module c.export = c, in Modul b können Sie die Variable c verwenden, um die Methode und die Methode aufzurufen des c-Objekts im Modul c.
Analog dazu kann Modul a schließlich auch die Eigenschaften und Methoden von Objekt b in Modul b aufrufen.
Unabhängig vom Modul können andere Module require("xx module") verwenden, um verschiedene Methoden im xx-Modul aufzurufen, solange module.export = xx-Modul verwendet wird.
Der endgültige Modulstatus lautet module.status = STATUS.COMPILED.
Module.prototype._use = function(ids, callback) {
var uris = discover(ids, this.uri); //Resolve['./a','jquery']
This._load(uris, function() { // Berechne das analysierte a, die Adresse des Jquery-Moduls [url1, url2] und rufe die _load-Methode auf.
//util.map: Lassen Sie alle Datenmitglieder gleichzeitig eine bestimmte Funktion ausführen und ein neues Array zurückgeben, das das Ergebnis des von den ursprünglichen Array-Mitgliedern ausgeführten Rückrufs ist
var args = util.map(uris, function(uri) {
return uri ?cachedModules[uri]._compile(): null;//Wenn die URL vorhanden ist, rufen Sie die _compile-Methode auf.
})
if (callback) { callback.apply(null, args) }
})
}
Zu diesem Zeitpunkt args = [module a.export, module jquery.export];
seajs.use(['./a','jquery'],function(a,$){
var num = a.a;
$('#J_A').text(num);
})
Zu diesem Zeitpunkt sind a und $ in der Funktion Modul a.export und Modul jquery.export.
Da ich derzeit JQuery-Quellcode und JQuery-Framework-Design studiere, möchte ich einige Erfahrungen teilen:
Ich habe im Internet viele Analysen des JQuery-Quellcodes gelesen, aber ich konnte es nicht mehr ertragen. Es macht wenig Sinn. Ich empfehle die JQuery-Quellcode-Analyse von Miaowei Classroom.
Das JavaScript-Framework-Design von Situ Zhengmei ist für mich persönlich schwierig, aber nachdem Sie es sorgfältig gelesen haben, werden Sie ein leitender Front-End-Ingenieur.
Ich empfehle Ihnen, Yu Bo’s sea.js zu lernen und es zu verwenden. Schließlich wurde es von den Chinesen selbst erstellt. Die neuen Projekte oder Refactorings unseres Unternehmens werden mit Seajs durchgeführt.
Der nächste Schritt besteht darin, den Quellcode der modularen Handbars und des MVC-Backbones oder des MVVM-Angulars zu lesen. Hier hoffe ich, dass mir jemand einen Rat geben kann, welche Bücher ich lesen sollte, welche Websites ich lesen sollte und welche Videos ich mir ansehen sollte, um schnell zu lernen.