J'ai analysé le code source de require.js il y a quelque temps. L'analyse globale était un peu générale, et le contenu était. un peu vide et flou. L'essence du traitement des dépendances requirejs, c'est la partie la plus échouée dans l'analyse du code source require.js.
Bien que je ne comprenne pas vraiment les détails de sa mise en œuvre, j'ai une compréhension globale de l'organisation de son code source et de l'exécution logique de base.
Cet article fait référence au code source sur Internet et analyse le simple chargeur de module implémenté par ses idées, visant à approfondir la connaissance et la compréhension de require.js.
Les premiers points clairs sont les suivants :
Chaque fois que la fonction require est appelée, un Context sera créé L'objet
L'objet Module représente l'objet module, et les opérations de base sont les méthodes prototypes de l'objet
Les deux ci-dessus les objets doivent implémenter ce module simple. Le noyau du chargeur, le flux de traitement pendant le processus de chargement est illustré dans la figure ci-dessous :
Les propriétés de l'objet Module sont :
mid : indique l'identifiant du module
src : chemin du module
nom : nom du module
deps : liste des dépendances des modules
callback : fonction de rappel
errback : fonction de gestion des erreurs
statut : statut du module
exports : Sortie du module correspondant à la séquence de paramètres de la fonction de rappel
L'objet prototype du Module a les méthodes suivantes :
init : Traitement d'initialisation de l'objet Module
fetch : créez un nœud de script et ajoutez-le au nœud d'élément
checkCycle : gère les dépendances cycliques et renvoie la liste actuelle des dépendances cycliques
handleDeps : gérer la liste des dépendances
changeStatus : modifiez l'état du module, en vérifiant principalement si le module est chargé avec succès
exécuter : Une fois tous les modules dépendants chargés avec succès, comment obtenir la liste des paramètres
En fait, traiter la liste des dépendances est définir et exiger Lors du traitement, les codes de traitement de la fonction définir et de la fonction exiger sont les suivants :
Regardez d'abord la fonction require, exemple :
require(['a', 'b'], function(a, b) { console.log(a, b); });
Comme le montre ce qui précède, la fonction require est appelée, la liste de dépendances est ['a', 'b'] et la fonction de rappel est function(a, b) {console.log(a, b);}
Comme le montre le code require, l'appel de Context Le constructeur crée un objet Context Regardons maintenant le traitement du constructeur Context : let Context = function(deps, callback, errback) {
this.cid = ++contextId; this.init(deps, callback, errback); } ; Context.prototype.init = function(deps, callback, errback) { this.deps = deps; this.callback = callback; this.errback = errback; contexts[this.cid] = this; } ;
La chose importante dans ce qui précède est contexts[this.cid ] = this ; Enregistrez l'objet Context actuel dans la collection d'objets de contextes globaux.
Appelez ensuite la fonction handleDeps, qui traite la liste de dépendances. Le code spécifique est le suivant : handleDeps: function() {
let depCount = this.deps ? this.deps.length : 0; // require.js中处理循环依赖的处理 let requireInDep = (this.deps || []).indexOf('require'); if (requireInDep !== -1) { depCount--; this.requireInDep = requireInDep; this.deps.splice(requireInDep, 1); } // 处理循环依赖情况 let cycleArray = this.checkCycle(); if (cycleArray) { depCount = depCount - cycleArray.length; } // depCount表示当前模块的依赖模块数,depCount为0表示模块中某一依赖加载完成 this.depCount = depCount; if (depCount === 0) { this.execute(); return; } // 遍历依赖列表,创建Module对象,并且将当前模块与其依赖的关系构建出来maps this.deps.forEach((depModuleName) => { if (!modules[depModuleName]) { let module = new Module(depModuleName); modules[module.name] = module; } if (!maps[depModuleName]) { maps[depModuleName] = []; } maps[depModuleName].push(this); } );
} Gestion des dépendances circulaires
La méthode officielle dans require.js consiste à gérer les dépendances circulaires dans ce code d'implémentation, ce qui consiste à transmettre require et require à nouveau dans la fonction de rappel. Pourquoi cela peut-il résoudre. dépendances circulaires ?
En ce qui concerne cette implémentation, require créera un objet Context une fois. Le code principal est le suivant : // Traitement des dépendances circulaires dans require.js let requireInDep = (this.deps || []).indexOf('require');
if (requireInDep !== -1) { depCount--; this.requireInDep = requireInDep; this.deps.splice(requireInDep, 1); } // 获取循环依赖 let cycleArray = this.checkCycle(); if (cycleArray) { depCount = depCount - cycleArray.length; } // execute函数中代码// 插入require到回调函数的参数列表中if (this.requireInDep !== -1 && this.requireInDep !== undefined) { arg.splice(this.requireInDep, 0, require); }
Conclusion
Ce que j'ai appris sur papier est enfin clair, et je me rends compte que cette question doit être mise en œuvre en implémentant un simple chargeur de module, l'idée et le traitement logique de require.js. le chargement du module devient plus clair.
Bien que require.js gère le chargement asynchrone des fichiers js différemment, l'essence est la même. require.js ajoute un nœud de script à la balise head et le script ajoute l'attribut async pour réaliser un chargement asynchrone.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!