Die Struktur von Webseiten wird immer komplexer. Sie kann als einfache APP betrachtet werden. Wenn Sie den gesamten Code wie zuvor in eine Datei packen, treten einige Probleme auf:
Globale Variablen beeinflussen sich gegenseitig
JavaScript-Dateien werden größer, was sich auf die Ladegeschwindigkeit auswirkt
Die Struktur ist verwirrend und schwer zu warten
var module1 = new Object({ _count : 0, m1 : function (){ //... }, m2 : function (){ //... } });
var module1 = (function(){ var _count = 0; var m1 = function(){ //... }; var m2 = function(){ //... }; return { m1 : m1, m2 : m2 }; })();
function add(a, b){ return a + b; } exports.add = add;
var math = require('math'); math.add(2,3);
require(['math'], function (math) {// require([module], callback); math.add(2, 3); });
define(function (){ // define([module], callback); var add = function (x,y){ return x+y; }; return { add: add }; });
so faul wie möglich!Der Unterschied zwischen der Verarbeitungsmethode abhängiger Module und AMD ist:
AMD wird im Voraus ausgeführt (Abhängigkeiten stehen im Vordergrund) und CMD wird verzögert ausgeführt Art und Weise (Abhängigkeiten sind in der Nähe).Die Art und Weise, ein Modul in CMD zu definieren, ist wie folgt:
define(function(require, exports, module) { var a = require('./a'); a.doSomething(); var b = require('./b'); b.doSomething(); });
Set onload und src beim Erstellen des Skript-Tags!Das ist tatsächlich der Fall, aber nicht ganz! Schauen wir uns zunächst den SeaJS-Code (sea-debug.js) an. Ein Modul kann während des Ladevorgangs die folgenden Zustände durchlaufen:
var STATUS = Module.STATUS = { // 1 - The `module.uri` is being fetched FETCHING: 1, // 2 - The meta data has been saved to cachedMods SAVED: 2, // 3 - The `module.dependencies` are being loaded LOADING: 3, // 4 - The module are ready to execute LOADED: 4, // 5 - The module is being executed EXECUTING: 5, // 6 - The `module.exports` is available EXECUTED: 6, // 7 - 404 ERROR: 7 }
-Objekt wird im Speicher verwendet, um Modulinformationen zu verwalten: Modul
function Module(uri, deps) { this.uri = uri this.dependencies = deps || [] // 依赖模块ID列表 this.deps = {} // 依赖模块Module对象列表 this.status = 0 // 状态 this._entry = [] // 在模块加载完成之后需要调用callback的模块 }
-Methode verwenden: seajs.use
seajs.use(‘./main’, function(main) {// 依赖及回调方法 main.init(); });
zu sehen: Module.prototype.load
Module.prototype.load = function() { var mod = this if (mod.status >= STATUS.LOADING) { return } mod.status = STATUS.LOADING var uris = mod.resolve() // 解析依赖模块的URL地址 emit("load", uris) for (var i = 0, len = uris.length; i < len; i++) { mod.deps[mod.dependencies[i]] = Module.get(uris[i])// 从缓存取或创建 } mod.pass(); // 将entry传递给依赖的但还没加载的模块 if (mod._entry.length) {// 本模块加载完成 mod.onload() return } var requestCache = {}; var m; // 加载依赖的模块 for (i = 0; i < len; i++) { m = cachedMods[uris[i]] if (m.status < STATUS.FETCHING) { m.fetch(requestCache) } else if (m.status === STATUS.SAVED) { m.load() } } for (var requestUri in requestCache) { if (requestCache.hasOwnProperty(requestUri)) { requestCache[requestUri]() } } }
. Ich konnte im Internet keinen relativ leicht verständlichen Artikel finden, also habe ich mir den Code angesehen und ihn erraten, und ich habe ihn ungefähr verstanden. Denken Sie nur an sein Ziel: _entry
Wenn alle abhängigen Module geladen sind, führen Sie die Callback-Funktion aus!Mit anderen Worten:
Der array_entry speichert eine Liste, welche Modulabhängigkeiten geladen werden dürfen, nachdem das aktuelle Modul geladen wurde (umgekehrte Beziehung der Abhängigkeiten)!Wenn beispielsweise Modul A von den Modulen B, C und D abhängt, lautet der Status nach dem Bestehen wie folgt: At Diesmal ist A
in 3, was bedeutet, dass es immer noch drei abhängige Module gibt, die nicht geladen wurden! Und wenn Modul B von den Modulen E und F abhängt, dann wird A beim Laden ebenfalls übergangen: remain
laden : Module.prototype.fetch
sendRequest
aus basierend auf dem Ergebnis. Nachdem alle abhängigen Module geladen wurden, wird die load
-Methode ausgeführt: error
onload
Module.prototype.onload = function() { var mod = this mod.status = STATUS.LOADED for (var i = 0, len = (mod._entry || []).length; i < len; i++) { var entry = mod._entry[i] if (--entry.remain === 0) { entry.callback() } } delete mod._entry }
bedeutet, dass alle Module, von denen es abhängt, geladen wurden! Dann wird zu diesem Zeitpunkt die Rückruffunktion ausgeführt: --entry.remain
entry.remain === 0
for (var i = 0, len = uris.length; i < len; i++) { exports[i] = cachedMods[uris[i]].exec(); } if (callback) { callback.apply(global, exports)// 执行回调函数 }
define
Führen Sie dann die Methodeaus, um Moduldaten zu generieren:
var exports = isFunction(factory) ? factory.call(mod.exports = {}, require, mod.exports, mod) : factory
然后执行你在seajs.use中定义的callback
方法:
if (callback) { callback.apply(global, exports) }
当你写的模块代码中require时,每次都会执行factory方法:
function require(id) { var m = mod.deps[id] || Module.get(require.resolve(id)) if (m.status == STATUS.ERROR) { throw new Error('module was broken: ' + m.uri) } return m.exec() }
到这里核心的逻辑基本上讲完了,补一张状态的转换图:
以后在用的时候就可以解释一些诡异的问题了!
模块化非常好用,因此在ECMAScript 6中也开始支持,但是浏览器支持还是比较堪忧的~~
Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die JavaScript-Modularisierung und SeaJs-Quellcode-Analyse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!