Angular.js で他のものに注入できる「もの」は何ですか? 質問する

Angular.js で他のものに注入できる「もの」は何ですか? 質問する

Angular の依存性注入を理解するのに少し苦労しています。質問ですが、コントローラー、ファクトリー、プロバイダーなどのどの「タイプ」を、同じ「タイプ」の他のインスタンスを含め、他のものに注入できるか説明してもらえますか?

私が実際に探しているのは、y/n で埋められたこの表です。同じ行/列のセルの場合、それは 1 つの「タイプ」の値を同じ「タイプ」の別のセルに注入することを意味します。

+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant       |          |            |           |         |        |          |         |       |
| Controller     |          |            |           |         |        |          |         |       |
| Directive      |          |            |           |         |        |          |         |       |
| Factory        |          |            |           |         |        |          |         |       |
| Filter         |          |            |           |         |        |          |         |       |
| Provider       |          |            |           |         |        |          |         |       |
| Service        |          |            |           |         |        |          |         |       |
| Value          |          |            |           |         |        |          |         |       |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+

ベストアンサー1

説明なしに「はい」と「いいえ」を表に記入するだけではなく、もう少し詳しく説明します。

[注記、書き終えた後に追加: 結局、これは予想していたよりもかなり長くなりました。最後に tl;dr がありますが、参考になれば幸いです。]

[この回答は AngularJS wiki にも追加されています:依存性注入を理解する]


プロバイダー($provide

サービス$provideはAngularに新しい注入可能なものをどのように作成するかを伝える役割を担っており、これらはサービスサービスは、プロバイダーは、 を使用するときに作成するものです$provide。プロバイダーの定義は、サービスproviderの メソッドを介して行われ、アプリケーションの関数に挿入するように要求することで、サービス$provideを取得できます。たとえば、次のようになります。$provideconfig

app.config(function($provide) {
  $provide.provider('greeting', function() {
    this.$get = function() {
      return function(name) {
        alert("Hello, " + name);
      };
    };
  });
});

ここでは、 というサービスの新しいプロバイダーを定義しましたgreeting。 という名前の変数を任意の注入greeting可能な関数 (コントローラーなど、これについては後で詳しく説明します) に注入することができ、Angular はプロバイダーの関数を呼び出して、サービスの新しいインスタンスを返します。 この場合、注入されるのは、名前に基づいてパラメーターとsa メッセージ$getを受け取る関数です。 次のように使用できます。namealert

app.controller('MainController', function($scope, greeting) {
  $scope.onClick = function() {
    greeting('Ford Prefect');
  };
});

さて、ここに秘訣があります。 factory、、servicevalueすべてプロバイダのさまざまな部分を定義するための単なるショートカットです。つまり、これらすべてを入力しなくてもプロバイダを定義する手段を提供します。たとえば、次のように記述できます。まったく同じプロバイダーちょうどこのような:

app.config(function($provide) {
  $provide.factory('greeting', function() {
    return function(name) {
      alert("Hello, " + name);
    };
  });
});

理解しておくことは重要なので、言い換えると、AngularJSは内部的にまったく同じコード上で書いたもの($provide.providerバージョン)のために私たち。文字通り、2 つのバージョンには 100% 違いはありません。valueはまったく同じように動作します。$get関数 (つまり、factory関数) から返されるものが常にまったく同じであれば、 を使用するとさらに少ないコードを書くことができますvalue。たとえば、サービスに対して常に同じ関数を返すのでgreeting、 を使用してそれを定義することもできますvalue

app.config(function($provide) {
  $provide.value('greeting', function(name) {
    alert("Hello, " + name);
  });
});

繰り返しますが、これはこの関数を定義するために使用した他の 2 つの方法と 100% 同一です。これは単に入力を節約する方法です。

app.config(function($provide) { ... })おそらく、私が使っているこの厄介な機能に気づいたでしょう。新しいプロバイダを定義して以来(どれでも上記のメソッドは非常に一般的なので、AngularJS は$providerモジュール オブジェクト上で直接メソッドを公開し、入力をさらに省きます。

var myMod = angular.module('myModule', []);

myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);

app.config(...)これらはすべて、以前使用したより詳細なバージョンと同じことを行います。

これまで省略してきた注入可能なものは ですconstant。今のところ、 と同じように機能すると言っても過言ではありませんvalue。違いが 1 つあることは後で説明します。

レビューする全てこれらのコードはちょうど同じこと:

myMod.provider('greeting', function() {
  this.$get = function() {
    return function(name) {
      alert("Hello, " + name);
    };
  };
});

myMod.factory('greeting', function() {
  return function(name) {
    alert("Hello, " + name);
  };
});

myMod.value('greeting', function(name) {
  alert("Hello, " + name);
});

インジェクター($injector

インジェクターは、提供されたコードを使用して、実際にサービスのインスタンスを作成する役割を担っています$provide(しゃれではありません)。注入された引数を取る関数を作成するときはいつでも、インジェクターが機能しているのがわかります。各 AngularJS アプリケーションには、アプリケーションの初回起動時に作成される単一のインジェクターがあります。注入可能な関数に$injector注入することで、そのインジェクターを取得できます(そう、インジェクターは自分自身を注入する方法を知っています!)。$injector$injector

を取得したら、サービス名を指定して呼び出す$injectorことで、定義されたサービスのインスタンスを取得できます。たとえば、get

var greeting = $injector.get('greeting');
greeting('Ford Prefect');

インジェクターは、関数にサービスを注入する役割も担います。たとえば、インジェクターのinvokeメソッドを使用して、任意の関数に魔法のようにサービスを注入することができます。

var myFunction = function(greeting) {
  greeting('Ford Prefect');
};
$injector.invoke(myFunction);

インジェクターはサービスのインスタンスのみを作成することに注意してください一度次に、プロバイダーがサービス名で返すものをキャッシュします。次にサービスを要求したときに、実際にまったく同じオブジェクトが取得されます。

それで、あなたの質問に答えると、サービスを注入することができます呼び出される関数は$injector.invoke。 これも

  • コントローラ定義関数
  • ディレクティブ定義関数
  • フィルタ定義関数
  • $getプロバイダーのメソッド(定義関数とも呼ばれるfactory

constants とs は常に静的な値を返すためvalue、インジェクター経由で呼び出されることはなく、したがって、それらに何かを注入することはできません。

プロバイダーの設定

provide、などがこんなに簡単なのにfactory、なぜわざわざメソッドを使って本格的なプロバイダを設定する必要があるのか​​と不思議に思うかもしれませんvalue。その答えは、プロバイダは多くの設定を可能にするからです。プロバイダ(またはAngularが提供するショートカットのいずれか)を介してサービスを作成すると、そのサービスの構築方法を定義する新しいプロバイダが作成されることはすでに述べました。しなかったここで言及しておきたいのは、これらのプロバイダーをアプリケーションのセクションに挿入してconfig、それらを操作できるということです。

まず、Angular はアプリケーションを フェーズconfigrunフェーズの 2 つのフェーズで実行します。configフェーズでは、これまで見てきたように、必要に応じてプロバイダーを設定できます。また、ディレクティブ、コントローラー、フィルターなどもここで設定されます。 フェーズではrun、ご想像のとおり、Angular が実際に DOM をコンパイルしてアプリを起動します。

これらのフェーズで実行する追加コードを関数myMod.configmyMod.run関数で追加できます。各関数は、特定のフェーズで実行する関数を受け取ります。最初のセクションで見たように、これらの関数は注入可能です。最初のコードサンプルでは、​​組み込みの$provideサービスを注入しました。ただし、注目すべき点は、このconfigフェーズでは、プロバイダーのみが注入できる。AUTO(モジュール内のサービス (および$provide)を除く$injector)。

例えば、次のようになります禁じられている:

myMod.config(function(greeting) {
  // WON'T WORK -- greeting is an *instance* of a service.
  // Only providers for services can be injected in config blocks.
});

あなたがするアクセスできるのはプロバイダーあなたが行ったサービスに対して:

myMod.config(function(greetingProvider) {
  // a-ok!
});

重要な例外が 1 つあります。constantは変更できないため、ブロック内に挿入できますconfig(これが との違いですvalue)。 は名前だけでアクセスされます (Providerサフィックスは不要)。

サービスにプロバイダーを定義すると、そのプロバイダーはserviceProviderという名前になりますservice。ここで はサービスの名前です。これで、プロバイダーの力を利用して、より複雑な処理を実行できるようになりました。

myMod.provider('greeting', function() {
  var text = 'Hello, ';

  this.setText = function(value) {
    text = value;
  };

  this.$get = function() {
    return function(name) {
      alert(text + name);
    };
  };
});

myMod.config(function(greetingProvider) {
  greetingProvider.setText("Howdy there, ");
});

myMod.run(function(greeting) {
  greeting('Ford Prefect');
});

これで、プロバイダーに という関数が作成され、これをsetText使用して をカスタマイズできます。alertブロック内でこのプロバイダーにアクセスし、configこのメソッドを呼び出してサービスをカスタマイズできます。最終的にアプリを実行すると、greetingサービスを取得して試用し、カスタマイズが有効になっているかどうかを確認できます。

これはより複雑な例なので、実際に動作するデモンストレーションを以下に示します。http://jsfiddle.net/BinaryMuse/9GjYg/

コントローラー($controller

コントローラー関数はに注入できますが、コントローラー自体は他のものに注入できません。これは、コントローラーがプロバイダー経由で作成されないためです。代わりに、$controllerコントローラーの設定を担当する組み込みの Angular サービスがあります。 を呼び出すとmyMod.controller(...)、実際にはこのサービスのプロバイダー前のセクションと同じです。

たとえば、次のようにコントローラーを定義するとします。

myMod.controller('MainController', function($scope) {
  // ...
});

実際にやっていることは次の通りです:

myMod.config(function($controllerProvider) {
  $controllerProvider.register('MainController', function($scope) {
    // ...
  });
});

その後、Angular がコントローラーのインスタンスを作成する必要があるときは、 サービスを使用します$controller(次に、 を使用して$injectorコントローラー関数を呼び出すため、その依存関係も注入されます)。

フィルターとディレクティブ

filterおよび はdirectiveとまったく同じように動作しますcontrollerfilterは というサービス$filterとそのプロバイダを使用し$filterProvider、 はdirectiveというサービス$compileとそのプロバイダを使用します$compileProvider。いくつかのリンク:

他の例と同様に、myMod.filterおよび はmyMod.directiveこれらのサービスを構成するためのショートカットです。


要約

まとめると、$injector.invoke 注入できるこれには、チャートから次のものが含まれます (ただし、これらに限定されません)。

  • コントローラ
  • 指令
  • 工場
  • フィルター
  • プロバイダー$get(プロバイダーをオブジェクトとして定義する場合)
  • プロバイダー関数(プロバイダーをコンストラクター関数として定義する場合)
  • サービス

プロバイダーは新しいサービスを作成する物に注入できる。 これも:

  • 絶え間ない
  • 工場
  • プロバイダー
  • サービス
  • 価値

とはいえ、組み込みのサービス$controller$filter できる注射すれば、使用これらのサービスを使用して、これらのメソッドで定義した新しいフィルターとコントローラーを取得します (定義したもの自体を他のものに挿入することはできませんが)。

それ以外では、インジェクターによって呼び出される関数は、プロバイダーが提供するサービスを使用して注入できます。制限はありません (ここに記載されているconfigおよび のrun違いを除く)。

おすすめ記事