Anstatt die Tabelle nur mit "Ja" und "Nein" ohne Erklärung auszufüllen, werde ich etwas näher darauf eingehen.
[Anmerkung, hinzugefügt nach Abschluss: Dies endete ... ziemlich viel länger als ich erwartet hatte. Unten ist ein tl; dr, aber ich hoffe, dies erweist sich als informativ.]
[Diese Antwort wurde auch dem AngularJS-Wiki hinzugefügt: Grundlegendes zur Abhängigkeitsinjektion ]
Der $provide
Dienst ist dafür verantwortlich, Angular mitzuteilen, wie neue injizierbare Dinge hergestellt werden sollen. Diese Dinge werden Dienste genannt . Services werden durch sogenannte Provider definiert , die Sie bei der Verwendung erstellen $provide
. Das Definieren eines Anbieters erfolgt über die provider
Methode des $provide
Dienstes. Sie können den $provide
Dienst abrufen, indem Sie ihn in die config
Funktion einer Anwendung einfügen. Ein Beispiel könnte ungefähr so sein:
app.config(function($provide) {
$provide.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
});
Hier haben wir einen neuen Anbieter für einen Dienst namens definiert greeting
. Wir können eine Variable mit dem Namen greeting
in jede injizierbare Funktion einfügen (wie Controller, dazu später mehr), und Angular ruft die $get
Funktion des Anbieters auf , um eine neue Instanz des Dienstes zurückzugeben. In diesem Fall wird eine Funktion injiziert, die einen name
Parameter und eine alert
Nachricht basierend auf dem Namen verwendet. Wir könnten es so verwenden:
app.controller('MainController', function($scope, greeting) {
$scope.onClick = function() {
greeting('Ford Prefect');
};
});
Hier ist der Trick. factory
, service
Und value
sind alle nur Verknüpfungen verschiedene Teile eines Providers zu definieren - das heißt, sie ein Mittel zur Definition eines Anbieters zur Verfügung stellen , ohne dass alle Sachen aus eingeben zu müssen. Zum Beispiel könnten Sie genau denselben Anbieter wie folgt schreiben :
app.config(function($provide) {
$provide.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
});
Es ist wichtig zu verstehen, also werde ich es umformulieren: Unter der Haube ruft AngularJS genau den Code auf , den wir oben (die $provide.provider
Version) für uns geschrieben haben. Es gibt buchstäblich 100% keinen Unterschied zwischen den beiden Versionen. value
funktioniert genauso - wenn alles, was wir von unserer $get
Funktion (auch bekannt als unsere factory
Funktion) zurückgeben würden, immer genau gleich ist, können wir mit noch weniger Code schreiben value
. Da wir beispielsweise immer dieselbe Funktion für unseren greeting
Service zurückgeben, können wir sie auch value
definieren:
app.config(function($provide) {
$provide.value('greeting', function(name) {
alert("Hello, " + name);
});
});
Auch dies ist zu 100% identisch mit den beiden anderen Methoden, mit denen wir diese Funktion definiert haben. Dies ist nur eine Möglichkeit, die Eingabe zu speichern.
Jetzt haben Sie wahrscheinlich diese nervige app.config(function($provide) { ... })
Sache bemerkt , die ich benutzt habe. Da das Definieren neuer Anbieter (über eine der oben genannten Methoden) so häufig ist, macht AngularJS die $provider
Methoden direkt auf dem Modulobjekt verfügbar, um noch mehr Eingabe zu sparen:
var myMod = angular.module('myModule', []);
myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);
Diese machen alle dasselbe wie die ausführlicheren app.config(...)
Versionen, die wir zuvor verwendet haben.
Das injizierbare, das ich bisher übersprungen habe, ist constant
. Im Moment ist es leicht zu sagen, dass es genauso funktioniert value
. Wir werden später sehen, dass es einen Unterschied gibt.
Zur Überprüfung , alle diese Stücke von Code tun , um die genaue gleiche Sache:
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);
});
Der Injektor ist dafür verantwortlich, Instanzen unserer Dienste mithilfe des von uns bereitgestellten Codes zu erstellen $provide
(kein Wortspiel beabsichtigt). Jedes Mal, wenn Sie eine Funktion schreiben, die injizierte Argumente akzeptiert, sehen Sie den Injektor bei der Arbeit. Jede AngularJS-Anwendung verfügt über eine einzelne Anwendung $injector
, die beim ersten Start der Anwendung erstellt wird. Sie können es erreichen, indem Sie es $injector
in eine injizierbare Funktion injizieren (ja, $injector
weiß, wie man sich selbst injiziert!)
Sobald Sie dies getan haben $injector
, können Sie eine Instanz eines definierten Dienstes abrufen, indem get
Sie ihn mit dem Namen des Dienstes aufrufen . Beispielsweise,
var greeting = $injector.get('greeting');
greeting('Ford Prefect');
Der Injektor ist auch für das Injizieren von Diensten in Funktionen verantwortlich. Mit der invoke
Methode des Injektors können Sie beispielsweise Dienste auf magische Weise in jede Funktion injizieren, die Sie haben .
var myFunction = function(greeting) {
greeting('Ford Prefect');
};
$injector.invoke(myFunction);
Sein bemerkenswert, dass der Injektor nur eine Instanz eines Dienstes erstellen einmal . Anschließend wird alles zwischengespeichert, was der Anbieter mit dem Namen des Dienstes zurückgibt. Wenn Sie das nächste Mal nach dem Service fragen, erhalten Sie genau das gleiche Objekt.
Um Ihre Frage zu beantworten, können Sie Dienste in jede Funktion$injector.invoke
einfügen , mit der aufgerufen wird . Das beinhaltet
- Controller-Definitionsfunktionen
- Richtliniendefinitionsfunktionen
- Filterdefinitionsfunktionen
- die
$get
Methoden der Anbieter (auch bekannt als die factory
Definitionsfunktionen)
Da constant
s und value
s immer einen statischen Wert zurückgeben, werden sie nicht über den Injektor aufgerufen, sodass Sie ihnen nichts injizieren können.
Anbieter konfigurieren
Sie wundern sich vielleicht , warum jemand einen vollwertigen Anbieter mit der einzurichten stören würde provide
Methode , wenn factory
, value
usw. sind so viel einfacher. Die Antwort ist, dass Anbieter viel Konfiguration zulassen. Wir haben bereits erwähnt, dass Sie beim Erstellen eines Dienstes über den Anbieter (oder eine der von Angular bereitgestellten Verknüpfungen) einen neuen Anbieter erstellen, der definiert, wie dieser Dienst aufgebaut ist. Was ich nicht erwähnt habe, ist, dass diese Anbieter in config
Abschnitte Ihrer Anwendung eingefügt werden können, damit Sie mit ihnen interagieren können!
Zunächst führt Angular Ihre Anwendung in zwei Phasen aus - der config
und run
-Phase. Die config
Phase, wie wir gesehen haben, ist , wo Sie alle Anbieter nach Bedarf einrichten. Hier werden auch Direktiven, Controller, Filter und dergleichen eingerichtet. In der run
Phase, wie Sie vielleicht erraten haben, kompiliert Angular Ihr DOM und startet Ihre App.
Sie können zusätzlichen Code hinzufügen, der in diesen Phasen mit den Funktionen myMod.config
und ausgeführt myMod.run
werden soll. Jede Funktion übernimmt eine Funktion, die während dieser bestimmten Phase ausgeführt werden soll. Wie wir im ersten Abschnitt gesehen haben, sind diese Funktionen injizierbar - wir haben den integrierten $provide
Service in unserem allerersten Codebeispiel injiziert . Bemerkenswert ist jedoch, dass während der config
Phase nur Anbieter injiziert werden können (mit Ausnahme der Dienste im AUTO
Modul - $provide
und $injector
).
Folgendes ist beispielsweise nicht zulässig :
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
Was Sie tun haben Zugriff zu alle sind Anbieter für Dienstleistungen , die Sie gemacht haben:
myMod.config(function(greetingProvider) {
// a-ok!
});
Es gibt eine wichtige Ausnahme: constant
s dürfen, da sie nicht geändert werden können, in config
Blöcke injiziert werden (so unterscheiden sie sich von value
s). Sie werden nur über ihren Namen aufgerufen (kein Provider
Suffix erforderlich).
Immer wenn Sie einen Anbieter für einen Dienst definiert haben, wird dieser Anbieter benannt serviceProvider
, wobei service
der Name des Dienstes lautet. Jetzt können wir die Macht der Anbieter nutzen, um etwas komplizierteres zu tun!
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');
});
Jetzt haben wir eine Funktion auf unserem Provider setText
, mit der wir unsere anpassen können alert
. Wir können in einem config
Block auf diesen Anbieter zugreifen, um diese Methode aufzurufen und den Dienst anzupassen. Wenn wir unsere App endlich ausführen, können wir den greeting
Service nutzen und ausprobieren, um festzustellen, ob unsere Anpassung wirksam wurde.
Da dies ein komplexeres Beispiel ist, finden Sie hier eine funktionierende Demonstration: http://jsfiddle.net/BinaryMuse/9GjYg/
Controller-Funktionen können injiziert werden, aber Controller selbst können nicht in andere Dinge injiziert werden. Dies liegt daran, dass Controller nicht über den Anbieter erstellt werden. Stattdessen gibt es einen integrierten Angular-Dienst namens $controller
, der für die Einrichtung Ihrer Controller verantwortlich ist. Wenn Sie anrufen myMod.controller(...)
, greifen Sie genau wie im letzten Abschnitt auf den Anbieter dieses Dienstes zu .
Wenn Sie beispielsweise einen Controller wie folgt definieren:
myMod.controller('MainController', function($scope) {
// ...
});
Was Sie tatsächlich tun, ist Folgendes:
myMod.config(function($controllerProvider) {
$controllerProvider.register('MainController', function($scope) {
// ...
});
});
Wenn Angular später eine Instanz Ihres Controllers erstellen muss, verwendet es den $controller
Dienst (der wiederum den verwendet $injector
, um Ihre Controller-Funktion aufzurufen, damit auch die Abhängigkeiten eingefügt werden).
Filter und Richtlinien
filter
und directive
arbeiten genauso wie controller
; filter
verwendet einen angerufenen Dienst $filter
und seinen Anbieter $filterProvider
, während directive
ein genannter Dienst $compile
und sein Anbieter verwendet werden $compileProvider
. Einige Links:
Gemäß den anderen Beispielen myMod.filter
und myMod.directive
sind Verknüpfungen , um diese Dienste zu konfigurieren.
Zusammenfassend kann also jede Funktion, mit der aufgerufen wird $injector.invoke
, injiziert werden . Dies beinhaltet aus Ihrem Diagramm (ist aber nicht beschränkt auf):
- Regler
- Richtlinie
- Fabrik
- Filter
- Anbieter
$get
(beim Definieren des Anbieters als Objekt)
- Provider-Funktion (wenn Provider als Konstruktorfunktion definiert wird)
- Bedienung
Der Anbieter erstellt neue Dienste , die in Dinge eingefügt werden können . Das beinhaltet:
- Konstante
- Fabrik
- Anbieter
- Bedienung
- Wert
Das sei gesagt, integrierte Dienste wie $controller
und $filter
kann injiziert werden, und Sie können verwenden diejenigen Service halten , die neuen Filter zu bekommen und Controllern Sie mit diesen Methoden definiert (auch wenn die Dinge , die Sie definiert nicht, selbst, in der Lage sein , in Dinge injiziert).
Andere als die, jede Injektor-aufgerufene Funktion kann mit jedem Provider-Service bereitgestellt injiziert werden - es gibt keine Beschränkung (mit Ausnahme der config
und run
Unterschieden , die hierin aufgelistet).