J'ai un peu de mal à comprendre l'injection de dépendances dans Angular. Ma question est donc la suivante: quelqu'un peut-il expliquer lequel des "types", comme Controller, Factory, Provider, etc. pouvons-nous injecter dans d'autres, y compris d'autres instances du même "type"?
Ce que je recherche en fait, c'est ce tableau rempli de y / n. Pour les cellules avec la même ligne / colonne, cela signifie injecter la valeur d'un "type" dans un autre avec le même "type"
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant | | | | | | | | |
| Controller | | | | | | | | |
| Directive | | | | | | | | |
| Factory | | | | | | | | |
| Filter | | | | | | | | |
| Provider | | | | | | | | |
| Service | | | | | | | | |
| Value | | | | | | | | |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
angularjs
dependency-injection
utilisateur1527166
la source
la source
Réponses:
Plutôt que de remplir le tableau avec «oui» et «non» sans aucune explication, je vais entrer un peu plus en détail.
[Remarque, ajouté après avoir terminé: cela a fini par être ... un peu plus long que prévu. Il y a un tl; dr en bas, mais j'espère que cela sera informatif.]
[Cette réponse a également été ajoutée au wiki AngularJS: Understanding Dependency Injection ]
Le fournisseur (
$provide
)Le
$provide
service est chargé de dire à Angular comment créer de nouvelles choses injectables; ces choses s'appellent des services . Les services sont définis par des éléments appelés fournisseurs , ce que vous créez lorsque vous utilisez$provide
. La définition d'un fournisseur se fait via laprovider
méthode sur le$provide
service, et vous pouvez mettre la main sur le$provide
service en demandant qu'il soit injecté dans laconfig
fonction d' une application . Un exemple pourrait être quelque chose comme ceci:Ici, nous avons défini un nouveau fournisseur pour un service appelé
greeting
; nous pouvons injecter une variable nomméegreeting
dans n'importe quelle fonction injectable (comme les contrôleurs, plus à ce sujet plus tard) et Angular appellera la$get
fonction du fournisseur afin de renvoyer une nouvelle instance du service. Dans ce cas, la chose qui sera injectée est une fonction qui prend unname
paramètre etalert
un message basé sur le nom. Nous pourrions l'utiliser comme ceci:Voici maintenant le truc.
factory
,service
et nevalue
sont que des raccourcis pour définir diverses parties d'un fournisseur - c'est-à-dire qu'ils fournissent un moyen de définir un fournisseur sans avoir à taper tout cela. Par exemple, vous pouvez écrire exactement le même fournisseur comme ceci:Il est important de comprendre, donc je vais reformuler: sous le capot, AngularJS appelle exactement le même code que nous avons écrit ci-dessus (la
$provide.provider
version) pour nous. Il n'y a littéralement aucune différence entre les deux versions.value
fonctionne exactement de la même manière - si tout ce que nous retournerions de notre$get
fonction (c'est-à-dire notrefactory
fonction) est toujours exactement le même, nous pouvons écrire encore moins de code en utilisantvalue
. Par exemple, puisque nous retournons toujours la même fonction pour notregreeting
service, nous pouvons également l'utiliservalue
pour la définir:Encore une fois, c'est 100% identique aux deux autres méthodes que nous avons utilisées pour définir cette fonction - c'est juste un moyen de sauvegarder un peu de frappe.
Maintenant, vous avez probablement remarqué cette
app.config(function($provide) { ... })
chose ennuyeuse que j'utilise. Puisque la définition de nouveaux fournisseurs (via l' une des méthodes ci-dessus) est si courante, AngularJS expose les$provider
méthodes directement sur l'objet module, pour économiser encore plus de frappe:Ceux-ci font tous la même chose que les
app.config(...)
versions plus verbeuses que nous avons utilisées précédemment.Le seul injectable que j'ai sauté jusqu'à présent est
constant
. Pour l'instant, il est assez facile de dire que cela fonctionne exactement commevalue
. Nous verrons qu'il y a une différence plus tard.Pour revoir , tous ces morceaux de code font exactement la même chose:
L'injecteur (
$injector
)L'injecteur est responsable de la création des instances de nos services en utilisant le code que nous avons fourni via
$provide
(sans jeu de mots). Chaque fois que vous écrivez une fonction qui prend des arguments injectés, vous voyez l'injecteur au travail. Chaque application AngularJS en a une$injector
qui est créée au premier démarrage de l'application; vous pouvez vous en emparer$injector
en l' injectant dans n'importe quelle fonction injectable (oui,$injector
sait comment s'injecter!)Une fois que vous l'avez fait
$injector
, vous pouvez obtenir une instance d'un service défini en l'appelantget
avec le nom du service. Par exemple,L'injecteur est également chargé d'injecter des services dans les fonctions; par exemple, vous pouvez par magie injecter des services dans n'importe quelle fonction que vous avez en utilisant la
invoke
méthode de l'injecteur ;Cela vaut la peine de noter que l'injecteur ne créer une instance d'un service une fois . Il met ensuite en cache tout ce que le fournisseur renvoie par le nom du service; la prochaine fois que vous demanderez le service, vous obtiendrez exactement le même objet.
Donc, pour répondre à votre question, vous pouvez injecter des services dans n'importe quelle fonction appelée avec
$injector.invoke
. Ceci comprend$get
méthodes des fournisseurs (aka lesfactory
fonctions de définition)Puisque
constant
s etvalue
s renvoient toujours une valeur statique, ils ne sont pas appelés via l'injecteur et vous ne pouvez donc pas leur injecter quoi que ce soit.Configuration des fournisseurs
Vous demandez peut - être pourquoi quelqu'un prendrait la peine de mettre en place un fournisseur à part entière avec la
provide
méthode sifactory
,value
etc. sont tellement plus facile. La réponse est que les fournisseurs autorisent beaucoup de configuration. Nous avons déjà mentionné que lorsque vous créez un service via le fournisseur (ou l'un des raccourcis fournis par Angular), vous créez un nouveau fournisseur qui définit la manière dont ce service est construit. Ce que je n'ai pas mentionné, c'est que ces fournisseurs peuvent être injectés dans desconfig
sections de votre application afin que vous puissiez interagir avec eux!Tout d'abord, Angular exécute votre application en deux phases - les phases
config
etrun
. Laconfig
phase, comme nous l'avons vu, est celle où vous pouvez configurer tous les fournisseurs si nécessaire. C'est également là que les directives, les contrôleurs, les filtres et autres sont configurés. Larun
phase, comme vous pouvez le deviner, est celle où Angular compile réellement votre DOM et démarre votre application.Vous pouvez ajouter du code supplémentaire à exécuter dans ces phases avec les fonctions
myMod.config
etmyMod.run
- chacune prend une fonction à exécuter pendant cette phase spécifique. Comme nous l'avons vu dans la première section, ces fonctions sont injectables - nous avons injecté le service intégré$provide
dans notre tout premier exemple de code. Cependant, il convient de noter que pendant laconfig
phase, seuls les fournisseurs peuvent être injectés (à l'exception des services duAUTO
module -$provide
et$injector
).Par exemple, ce qui suit n'est pas autorisé :
Ce que vous n'avez accès à tous sont les fournisseurs de services que vous avez fait:
Il y a une exception importante: les
constant
s, puisqu'ils ne peuvent pas être modifiés, peuvent être injectés à l'intérieur deconfig
blocs (c'est ainsi qu'ils diffèrent devalue
s). Ils sont accessibles uniquement par leur nom (pas deProvider
suffixe nécessaire).Chaque fois que vous avez défini un fournisseur pour un service, ce fournisseur est nommé
serviceProvider
, oùservice
est le nom du service. Maintenant, nous pouvons utiliser la puissance des fournisseurs pour faire des choses plus compliquées!Maintenant, nous avons une fonction sur notre fournisseur appelée
setText
que nous pouvons utiliser pour personnaliser notrealert
; nous pouvons accéder à ce fournisseur dans unconfig
bloc pour appeler cette méthode et personnaliser le service. Lorsque nous exécutons enfin notre application, nous pouvons récupérer legreeting
service et l'essayer pour voir que notre personnalisation a pris effet.Puisqu'il s'agit d'un exemple plus complexe, voici une démonstration de travail: http://jsfiddle.net/BinaryMuse/9GjYg/
Contrôleurs (
$controller
)Les fonctions du contrôleur peuvent être injectées dans, mais les contrôleurs eux-mêmes ne peuvent pas être injectés dans d'autres choses. C'est parce que les contrôleurs ne sont pas créés via le fournisseur. Au lieu de cela, il existe un service Angular intégré appelé
$controller
qui est responsable de la configuration de vos contrôleurs. Lorsque vous appelezmyMod.controller(...)
, vous accédez en fait au fournisseur de ce service , comme dans la dernière section.Par exemple, lorsque vous définissez un contrôleur comme celui-ci:
Voici ce que vous faites réellement:
Plus tard, quand Angular a besoin de créer une instance de votre contrôleur, il utilise le
$controller
service (qui à son tour utilise le$injector
pour appeler votre fonction de contrôleur afin qu'il obtienne également ses dépendances injectées).Filtres et directives
filter
etdirective
fonctionnent exactement de la même manière quecontroller
;filter
utilise un service appelé$filter
et son fournisseur$filterProvider
, tandisdirective
qu'utilise un service appelé$compile
et son fournisseur$compileProvider
. Quelques liens:Comme dans les autres exemples,
myMod.filter
etmyMod.directive
sont des raccourcis pour configurer ces services.Donc, pour résumer, toute fonction appelée avec
$injector.invoke
peut être injectée dans . Cela inclut, à partir de votre graphique (mais sans s'y limiter):$get
(lors de la définition du fournisseur comme objet)Le fournisseur crée de nouveaux services qui peuvent être injectés dans les choses . Ceci comprend:
Cela dit, les services intégrés aiment
$controller
et$filter
peuvent être injectés, et vous pouvez utiliser ces services pour obtenir les nouveaux filtres et contrôleurs que vous avez définis avec ces méthodes (même si les éléments que vous avez définis ne sont pas, par eux-mêmes, capables d'être injecté dans les choses).En dehors de cela, toute fonction invoquée par l'injecteur peut être injectée avec n'importe quel service fourni par le fournisseur - il n'y a aucune restriction (autre que les
config
et lesrun
différences énumérées ici).la source
Le point que BinaryMuse fait valoir dans sa réponse étonnante sur les fournisseurs, les usines et les services est extrêmement important.
Voici une image qui, je pense, peut illustrer visuellement son propos:
(source: simplygoodcode.com )
la source
Excellente réponse de Michelle. Je veux juste souligner que des directives peuvent être injectées. Si vous avez une directive nommée
myThing
, vous pouvez l'injecter avecmyThingDirective
: Voici un exemple artificiel .L'exemple ci-dessus n'est pas très pratique, mais la possibilité d'injecter une directive est utile lorsque vous souhaitez décorer cette directive .
la source