Es fällt mir ein wenig schwer, die Abhängigkeitsinjektion in Angular zu verstehen. Meine Frage ist also, kann jemand erklären, welchen der "Typen" wie Controller, Factory, Provider usw. wir in andere injizieren können, einschließlich anderer Instanzen desselben "Typs"?
Was ich eigentlich suche, ist diese Tabelle mit j / n gefüllt. Für Zellen mit derselben Zeile / Spalte bedeutet dies, dass der Wert eines "Typs" in einen anderen Wert mit demselben "Typ" eingefügt wird.
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant | | | | | | | | |
| Controller | | | | | | | | |
| Directive | | | | | | | | |
| Factory | | | | | | | | |
| Filter | | | | | | | | |
| Provider | | | | | | | | |
| Service | | | | | | | | |
| Value | | | | | | | | |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
angularjs
dependency-injection
user1527166
quelle
quelle
Antworten:
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 Anbieter (
$provide
)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 dieprovider
Methode des$provide
Dienstes. Sie können den$provide
Dienst abrufen, indem Sie ihn in dieconfig
Funktion einer Anwendung einfügen. Ein Beispiel könnte ungefähr so sein:Hier haben wir einen neuen Anbieter für einen Dienst namens definiert
greeting
. Wir können eine Variable mit dem Namengreeting
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 einenname
Parameter und einealert
Nachricht basierend auf dem Namen verwendet. Wir könnten es so verwenden:Hier ist der Trick.
factory
,service
Undvalue
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 :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 unserefactory
Funktion) zurückgeben würden, immer genau gleich ist, können wir mit noch weniger Code schreibenvalue
. Da wir beispielsweise immer dieselbe Funktion für unserengreeting
Service zurückgeben, können wir sie auchvalue
definieren: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: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 funktioniertvalue
. 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:
Der Injektor (
$injector
)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, indemget
Sie ihn mit dem Namen des Dienstes aufrufen . Beispielsweise,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 .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$get
Methoden der Anbieter (auch bekannt als diefactory
Definitionsfunktionen)Da
constant
s undvalue
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 , wennfactory
,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 inconfig
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
undrun
-Phase. Dieconfig
Phase, wie wir gesehen haben, ist , wo Sie alle Anbieter nach Bedarf einrichten. Hier werden auch Direktiven, Controller, Filter und dergleichen eingerichtet. In derrun
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ührtmyMod.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 derconfig
Phase nur Anbieter injiziert werden können (mit Ausnahme der Dienste imAUTO
Modul -$provide
und$injector
).Folgendes ist beispielsweise nicht zulässig :
Was Sie tun haben Zugriff zu alle sind Anbieter für Dienstleistungen , die Sie gemacht haben:
Es gibt eine wichtige Ausnahme:
constant
s dürfen, da sie nicht geändert werden können, inconfig
Blöcke injiziert werden (so unterscheiden sie sich vonvalue
s). Sie werden nur über ihren Namen aufgerufen (keinProvider
Suffix erforderlich).Immer wenn Sie einen Anbieter für einen Dienst definiert haben, wird dieser Anbieter benannt
serviceProvider
, wobeiservice
der Name des Dienstes lautet. Jetzt können wir die Macht der Anbieter nutzen, um etwas komplizierteres zu tun!Jetzt haben wir eine Funktion auf unserem Provider
setText
, mit der wir unsere anpassen könnenalert
. Wir können in einemconfig
Block auf diesen Anbieter zugreifen, um diese Methode aufzurufen und den Dienst anzupassen. Wenn wir unsere App endlich ausführen, können wir dengreeting
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 (
$controller
)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 anrufenmyMod.controller(...)
, greifen Sie genau wie im letzten Abschnitt auf den Anbieter dieses Dienstes zu .Wenn Sie beispielsweise einen Controller wie folgt definieren:
Was Sie tatsächlich tun, ist Folgendes:
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
unddirective
arbeiten genauso wiecontroller
;filter
verwendet einen angerufenen Dienst$filter
und seinen Anbieter$filterProvider
, währenddirective
ein genannter Dienst$compile
und sein Anbieter verwendet werden$compileProvider
. Einige Links:Gemäß den anderen Beispielen
myMod.filter
undmyMod.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):$get
(beim Definieren des Anbieters als Objekt)Der Anbieter erstellt neue Dienste , die in Dinge eingefügt werden können . Das beinhaltet:
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
undrun
Unterschieden , die hierin aufgelistet).quelle
Der Punkt, den BinaryMuse in ihrer erstaunlichen Antwort darauf macht, dass Anbieter, Fabriken und Dienstleistungen alle dasselbe sind, ist äußerst wichtig.
Unten ist ein Bild, von dem ich denke, dass es ihren Standpunkt visuell veranschaulichen kann:
(Quelle: simplygoodcode.com )
quelle
Tolle Antwort von Michelle. Ich möchte nur darauf hinweisen, dass Direktiven injiziert werden können. Wenn Sie eine Direktive mit dem Namen haben
myThing
, können Sie sie einfügenmyThingDirective
: Hier ist ein erfundenes Beispiel .Das obige Beispiel ist nicht sehr praktisch, jedoch ist die Möglichkeit, eine Direktive einzufügen, nützlich, wenn Sie diese Direktive dekorieren möchten .
quelle