ホームページ  >  記事  >  ウェブフロントエンド  >  jsを使用して簡単なモジュールローダーを実装する方法

jsを使用して簡単なモジュールローダーを実装する方法

一个新手
一个新手オリジナル
2017-10-11 10:07:231596ブラウズ


前書き

以前、require.js のソースコードを分析しましたが、全体的な分析は少し大雑把で、内容が少し空っぽで、requirejs の依存関係処理の本質が掴めていませんでした。 require.js ソースコードの最も失敗した分析場所。

実装の詳細はよくわかりませんが、ソースコードの構成と基本的なロジックの実行については全体的に理解しています。

この記事は、インターネット上のソースコードを参照し、そのアイデアによって実装された単純なモジュールローダーを分析し、require.js の知識と理解を深めることを目的としています。

実装アイデア

まず、次の点が明確です:

  • require関数が呼び出されるたびに、Contextオブジェクトが作成されます

  • Moduleオブジェクトはモジュールオブジェクトを表し、基本的な操作は、このオブジェクトのプロトタイプです。メソッド

上記の 2 つのオブジェクトは、この単純なモジュール ローダーの実装の中核です。ロード プロセス中の処理フローは、次の図に示すとおりです。 Module オブジェクトは次のとおりです:
jsを使用して簡単なモジュールローダーを実装する方法
mid: モジュール ID を表します jsを使用して簡単なモジュールローダーを実装する方法代码 src: モジュールパス

名前: モジュール名

deps: モジュール依存関係リスト

コールバック: コールバック関数
errback: エラー処理関数

ステータス: モジュールのステータス
Exports: コールバック関数のパラメータ列に対応するモジュール出力


Moduleのプロトタイプオブジェクトには以下のメソッドがあります:


init: Moduleオブジェクトの初期化処理

fetch: スクリプト ノードを作成し、要素ノードに追加します
checkCycle: 循環依存関係を処理し、現在の循環依存関係リストを返します

handleDeps: ハンドル依存関係リスト

changeStatus: モジュールのステータスを変更します。主にモジュールが正常にロードされたかどうかを処理します
実行: すべての依存モジュールが正常にロードされた後、パラメータリストを取得する方法




依存関係リストの処理方法

実際、依存関係リストの処理はdefineとrequireの処理コードで処理されます。 function と require 関数は次のとおりです:

まず require 関数を見てください。例:

require(['a', 'b'], function(a, b) {
    console.log(a, b);
});

上記からわかるように、require 関数が呼び出されるときの依存関係リストは ['a', 'b ']、コールバック関数は function(a, b) {console.log( a, b);}
jsを使用して簡単なモジュールローダーを実装する方法 require コードからわかるように、Context コンストラクターを呼び出して Context オブジェクトを作成します。 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;
}
;

上記で重要なのは、現在の Context オブジェクトをグローバル コンテキスト オブジェクトに登録することです。コレクション。

次に、依存関係リストを処理する handleDeps 関数を呼び出します。 具体的なコードは次のとおりです: 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);
}
);

}
循環依存関係の処理


この実装コードは循環依存関係を処理します。 require.js の公式メソッドは、コールバック関数で require と require を再度渡すことです。なぜこれで循環依存関係が解決できるのでしょうか? この実装に関する限り、require は Context オブジェクトを一度作成するためです。メインコードは次のとおりです: // 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);
}

結論

紙の上で完成Jue Qian 氏は、この問題を実装する必要があることを認識しており、単純なモジュール ローダーを実装することで、require.js モジュールのロードの概念と論理処理がより明確になります。

require.js は js ファイルの非同期読み込みの処理方法が異なりますが、本質は同じです。require.js は head タグに script ノードを追加し、スクリプトは非同期読み込みを実現するために async 属性を追加します。

以上がjsを使用して簡単なモジュールローダーを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。