English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Angular Moduleの宣言とオーバーロードインスタンスの取得コード

moduleはangularの中で重要なモジュールの組織方法であり、一つの密接に関連するビジネスコンポーネント(controller、service、filter、directiveなど)をまとめて封装する能力を提供します。このようにすることで、コードをビジネス領域の問題ごとにmoduleで封装し、moduleの依存注入を利用して関連するモジュールの内容を注入することで、より良い「注目の分離」を達成し、より良い「高内聚低耦合」を実現することができます。「高内聚低耦合」は面向オブジェクト設計原則から来ています。内聚とはモジュールまたはオブジェクト内部の完全性を指し、密接に関連するロジックは同一のモジュール、オブジェクトなどのコードユニットに封装されるべきであり、各所に分散されるべきではありません;耦合とはモジュール、オブジェクトなどのコードユニット間の依存度を指し、あるモジュールの修正が別のモジュールに影響を与える場合、これらのモジュールは相互に依存して緊密に結びついていることを示しています。

同時にmoduleも私たちのangularコードのエントリーポイントであり、まずmoduleを宣言する必要があります。その後、angularの中で他のコンポーネント要素、例えばcontroller、service、filter、directive、configコードブロック、runコードブロックなどを定義することができます。

moduleの定義は「angular.module('com.ngbook.demo', [])」です。module関数には、パラメータを渡すことができます。3以下のパラメータが含まれます:

  1. name:モジュールの定義名です。これはユニークで必須のパラメータであり、後で他のモジュールに注入されたり、ngAPPディレクティブでアプリケーションのメインモジュールが宣言されます;
  2. requires:モジュールの依存関係です。これは、このモジュールが依存する他のモジュールを宣言するパラメータです。特に注意してください:ここにモジュールの依存関係を宣言しない場合、依存モジュールのコンポーネントを使用することはできません;これはオプションのパラメータです。
  3. configFn:モジュールの起動設定関数です。angularのconfigフェーズでこの関数が呼び出され、モジュール内のコンポーネントのインスタンス化前に特定の設定を行います。例えば、私たちがよく見るように$routeProviderでアプリケーションのルート情報を設定します。これは「module.config」関数と同等であり、その代わりに「module.config」関数を使用することをお勧めします。これはオプションのパラメータです。

angular.moduleメソッドに対して、私たちがよく使う方法はいくつかあります。その中には、angular.module('com.ngbook.demo', [オプション依存関係])とangular.module('com.ngbook.demo')があります。注意してください、これらは全く異なる方法です。一つはmoduleを宣言して作成する方法であり、もう一つは既に宣言されたmoduleを取得する方法です。アプリケーションでは、moduleの宣言は一度だけ行うべきであり、moduleの取得は複数回可能です。angularコンポーネントを独立して別のファイルに分離して、moduleファイルでmoduleを宣言し、他のコンポーネントはmoduleをインポートするようにします。注意点として、バンドルまたはscriptの方法でインポートする際には、まずmoduleの宣言ファイルをロードし、その後他のコンポーネントモジュールをロードする必要があります。

angularの中国コミュニティ群で、時々「ng:areq」エラーについて尋ねる学生がいます:

 [ng:areq] 引数 'DemoCtrl' は関数ではありません、undefinedが取得されました!

これは、controllerの定義を忘れたり、moduleを複数回宣言してしまったためによく起こります。moduleを複数回宣言すると、前のmoduleの定義情報がクリアされてしまい、そのためプログラムが定義されたコンポーネントを見つけることができません。これについては、angularのソースコードからも分かります(loader.jsから):

function setupModuleLoader(window) {
      ...
      function ensure(obj, name, factory) {
        return obj[name] || (obj[name] = factory());
      }
      var angular = ensure(window, 'angular', Object);
      return ensure(angular, 'module', function() {
        var modules = {};
        return function module(name, requires, configFn) {
          var assertNotHasOwnProperty = function(name, context) {
            if (name === 'hasOwnProperty') {
              throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
            }
          };
          assertNotHasOwnProperty(name, 'module');
          if (requires && modules.hasOwnProperty(name)) {
            modules[name] = null;
          }
          return ensure(modules, name, function() {
            if (!requires) {
              throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled ", +
                "the module name or forgot to load it. If registering a module ensure that you ", +
                "specify the dependencies as the second argument.", name);
            }
            var invokeQueue = [];
            var runBlocks = [];
            var config = invokeLater('$injector', 'invoke');
            var moduleInstance = {
              _invokeQueue: invokeQueue,
              _runBlocks: runBlocks,
              requires: requires,
              name: name,
              provider: invokeLater('$provide', 'provider'),
              factory: invokeLater('$provide', 'factory'),
              service: invokeLater('$provide', 'service'),
              value: invokeLater('$provide', 'value'),
              constant: invokeLater('$provide', 'constant', 'unshift'),
              animation: invokeLater('$animateProvider', 'register'),
              filter: invokeLater('$filterProvider', 'register'),
              controller: invokeLater('$controllerProvider', 'register'),
              directive: invokeLater('$compileProvider', 'directive'),
              config: config,
              run: function(block) {
                runBlocks.push(block);
                return this;
              }
            };
            if (configFn) {
              config(configFn);
            }
            return moduleInstance;
            function invokeLater(provider, method, insertMethod) {
              return function() {
                invokeQueue[insertMethod || 'push']([provider, method, arguments]);
                return moduleInstance;
              };
            }
          });
        };
      });
    }

コードでは、angularが起動時にグローバルなangularオブジェクトを設定し、そのangularオブジェクト上でmodule APIを公開することを学ぶことができます。module APIのコードでは、最初の行の命令文が明確に見られます。moduleの名前はhasOwnPropertyで始まってはなりません。そうしないと「badname」エラーメッセージが投げられます。その後、nameパラメータが渡された場合、それがmoduleを宣言するためのものであることを示し、既存のmodule情報を削除しnullにします。

moduleInstance の定義から、angular.module が公開する API には以下があります:invokeQueue、runBlocks、requires、name、provider、factory、servic、value、constant、animation、filter、controller、directive、config、run。そのうち、invokeQueue と runBlocks は名前で約束されたプライベートプロパティであり、使用しないでください。他の API は、私たちがよく使用する angular コンポーネントの定義方法です。invokeLater コードから、この種の angular コンポーネントの定義の返り値が moduleInstance インスタンスであることがわかります。これにより、スムーズな API が形成され、これらのコンポーネントをリンク式に定義することをお勧めします。全局の module 変数を宣言するのではなく、これらのコンポーネントをリンク式に定義することをお勧めします。

最後に、第3引数 configFn が渡された場合、それを config 情報に設定し、angular が config 開始段階に入ると、それらは順次実行され、angular アプリケーションや angular コンポーネント(serviceなど)のインスタンス化前に設定を行います。

以上が Angular Module の声明とオーバーロードの情報の整理です。今後も関連する情報を追加していく予定です。皆様の本サイトへのサポートに感謝します!

声明:本文の内容はインターネットから取得しており、著作権者はすべての権利を有しています。インターネットユーザーにより自発的に貢献し、自己でアップロードされています。本サイトは所有権を持ちません。また、人工的な編集は行われていません。著作権侵害を疑う内容が見つかった場合は、メールを notice#w までご送信ください。3codebox.com(メールを送信する際は、#を@に変更してください。)を通じて報告を行い、関連する証拠を提供してください。一旦確認がとりついたら、本サイトは即座に侵害する疑いのあるコンテンツを削除します。

おすすめ