しかし、違います。 Steveがスクリプトの
onload
/
onreadystatechange
についてメモの冒頭で言及しているのも不思議ではありません。 それらを使用して、特定のモジュールのロードの最後にコードを一意にバインドできます。 ポイントは小さいです。このコードを何らかの方法で定義する必要があります。
解決策1:ブートツリー
特定のページでモジュールの読み込み順序を決定する最も簡単な方法として、依存関係ツリーを含むグローバル配列を提供できます。 たとえば、これ:
var modules = [ [0、 'item1'、function(){ アラート(「item1がロードされました」); }]、 [1、 'item2'、function(){ アラート(「item2がロードされました」); }]、 [1、 'item3'、function(){ アラート(「item3がロードされました」); }] ];
この配列の要素として別の配列があります。 最初の要素は、親(要素がルートであり、すぐにロードする必要がある場合は
0
)を示し、次にファイル名またはそのエイリアスを示します。 最後は、ロードすることで実行できる任意の機能です。
この構造の使用方法を見てみましょう。
/ *モジュールの列挙と読み込み* / function load_by_parent(i){ i = i || 0; var len = modules.length、 モジュール; / *モジュールツリーを反復処理* / while(len--){ module = modules [len]; / *そして必要な要素をロードします* / if(!module [0]){ ローダー(len); } } } / *ローダー関数を宣言します* / 関数ローダー(i){ var module = modules [i]; / *新しいスクリプト要素を作成* / var script = document.createElement( 'script'); script.type = 'text / javascript'; / *ファイル名を設定* / script.src = module [1] + '.js'; / *タグ内のテキストをロード時に開始するように設定します* / script.text = module [2]; / *現在のモジュールインデックスを記憶する* / script.title = i + 1; / * IEのブートハンドラを設定します* / script.onreadystatechange = function(){ if(this.readyState === 'loaded'){ / *モジュールを繰り返し処理し、ロードする必要があるモジュールを探します* / load_by_parent(this.title); } }; / *残りのロードハンドラーを設定します* / script.onload = function(e){ / *タグ内のテキストを実行します(Operaにのみ必要)* / if(/opera/i.test(navigator.userAgent)){ eval(e.target.innerHTML); } / *モジュールを反復処理し、ロードする必要があるモジュールを探します* / load_by_parent(this.title); }; / *タグをドキュメントに添付します* / document.getElementsByTagName( 'head')[0] .appendChild(スクリプト); } / *ルート要素をロード* / load_by_parent();
ページの読み込みイベントでルート要素の読み込みを行い、関数自体をライブラリで取得したり、ページで直接宣言したりできます。 各ページにツリーを設定することにより、任意の数のJavaScriptモジュールを非同期的にロードする際の完全な柔軟性が得られます。 この場合、依存関係は「ルートからトップへ」解決されます。どの基本コンポーネントをダウンロードするかを知ってから、より高度なコンポーネントをダウンロードする必要があります。
解決策2:DOMツリーを介した読み込み
さらに、 Andrei Suminはすでに同様の問題に対処しており、 JSXライブラリの形式で彼のソリューションを提案したことを思い出しました。これにより、DOMツリーを通じて依存関係のリストを割り当てることができます。 これを行うには、ユーザーと対話するためにモジュールの読み込みを必要とする要素に
jsx-component
プレフィックスを持つクラスが割り当てられ、次にコンポーネントのリストが続きます。 ライブラリ自体はDOMツリーをバイパスし、ロードする必要のあるすべてのモジュールを見つけて、その後それらをロードします。 ただ素晴らしい。
しかし、このモジュールをロードするためのハンドラーを変更する必要がある場合はどうでしょうか? 設定方法 JSX自体は、DOMツリーの必須ノードの属性を使用して、これらのモジュールのパラメーターを純粋に決定します。 これは非常に便利です。結局、この方法でモジュール初期化子を割り当てることもできます。
このライブラリを使用すると、モジュールのリロードを追跡したり、接続に問題がある場合にモジュールをロードしたり、エイリアスシステムを介して異なるモジュールを1つのソースファイルに結合することもできます。 したがって、任意のモジュールツリーを非同期にロードする問題は解決されます。 JSXの場合、タスクは逆の順序で解決されます。メインファイル(依存関係ツリーの最上部)を指定し、必要なすべてのモジュールを既に読み込むか、モジュールが読み込まれていることを確認します。
それだけですか?
解決策3:JSX + YASS
ほぼ。 熟考した後、JSXは、柔軟で動的なクライアントアプリケーションの基盤となるモジュラーシステムを構築するための基盤として採用されました。 上記の両方のアプローチを組み合わせることで、このようなシステムの目に見える機能要件をすべて確保することができました。
たとえば、HTMLコードの次のセクションを考えます。
<div id = "item1" class = "yass-module-utils-base-dom"> <span id = "item2" class = "yass-module-dom" title = "_( '#item2')[0] .innerHTML = 'component is loading ...';"> </ span> </ div>
それが提供する読み込みロジックを見てみましょう:
- YASSは、初期化時にドキュメントのDOMツリーをバイパスし、クラス
yass-module-*
持つすべてのノードを選択します。 - その後、2つのモジュールロードフローが形成されます:
utils-base-dom
およびdom
。 さらに、後者の場合、ロードは行われません:ローダーはdom
コンポーネントの状態がloaded
に設定されるまで待機し、その後title
この要素のtitle
書かれたコード(この場合はspan
)を(eval
を介して)実行しspan
。 - 最初のロードストリームは、
yass.dom.js
、yass.base.js
およびyass.utils.js
3つのファイルをサーバーから非同期的に呼び出します。 これらのすべてのモジュールをロードすることにより(この場合、依存チェーンで呼び出されるため、dom
はutils
依存するbase
に依存するため)、対応する初期化関数が呼び出されます(定義されている場合)。 したがって、2種類のハンドラーが可能です。コンポーネントをロードした直後(チェーン内のすべてのコンポーネントに対して呼び出されます)とコンポーネントの特定のチェーン全体をロードした後(この場合はutils-base-dom
)。 - 何らかの方法でチェーンを拡張したい場合は、指定された各ファイルの最後に、他のチェーン(たとえば、
base-callbacks
)のロードを指定できます。これにより、callbacks
を受け取る前にbase
モジュールのロードが「フリーズ」されcallbacks
。 次のようにしてこれを行うことができます(base
モジュールの依存関係を拡張していることに留意してください)。
_.load( 'callbacks-base');
- 前の手順は、DOMツリー自体を使用して実行することもでき
yass-module-callbacks-base
。任意の要素に対してyass-module-callbacks-base
クラスを登録する必要がありyass-module-callbacks-base
。 これにより、目的のチェーンが依存関係ツリーに追加されます。
明確にするため、上記のロード可能なモジュールの最終ツリーは次のように表すことができます。
dom ->ベース -> utils ->コールバック
さらに、次のページでは、 より複雑なバージョンのツリーをロードするプロセスを示しています 。 注意:遅延がないため、非常に迅速に動作します:)
当然、指定されたすべての機能は既に最新バージョンのYASSに追加されています。 レビューを使用して書き始めることができます。
PS JSXサイトはまだ横たわっています(habraeffectが怖いですか?)、 Googleキャッシュから情報を引き出すことができます。