Quelles sont les différences entre ces deux et quels sont les cas d'utilisation pour chacun?
Les documents ne sont pas vraiment utiles:
forRoot crée un module qui contient toutes les directives, les routes données et le service du routeur lui-même.
forChild crée un module qui contient toutes les directives et les routes données, mais n'inclut pas le service de routeur.
Ma vague supposition est que l'un est pour le module «principal» et l'autre pour tous les modules importés (puisqu'ils auraient déjà le service disponible à partir du module principal), mais je ne peux pas vraiment penser à un cas d'utilisation.
RouterService
pour une seule application Angular2.forRoot
va initialiser ce service et l'enregistrer dans DI avec une configuration de route, tandisforChild
que n'enregistrera que des configurations de route supplémentaires et dira à Angular2 de réutiliser leRouterService
quiforRoot
a créé.Réponses:
Je suggère fortement de lire cet article:
Module avec prestataires
Lorsque vous importez un module, vous utilisez généralement une référence à la classe de module:
De cette façon, tous les fournisseurs enregistrés sur le module
A
seront ajoutés à l'injecteur racine et disponibles pour l'ensemble de l'application.Mais il existe un autre moyen d'enregistrer un module auprès de fournisseurs comme celui-ci:
Cela a les mêmes implications que le précédent.
Vous savez probablement que les modules chargés paresseusement ont leur propre injecteur. Supposons donc que vous souhaitiez vous inscrire
AService
pour être disponible pour l'ensemble de l'application, mais que certains neBService
soient disponibles que pour les modules à chargement différé. Vous pouvez refactoriser votre module comme ceci:Désormais,
BService
il ne sera disponible que pour les modules enfants chargés tardivement etAService
sera disponible pour l'ensemble de l'application.Vous pouvez réécrire ce qui précède en tant que module exporté comme ceci:
En quoi est-ce pertinent pour RouterModule?
Supposons qu'ils soient tous deux accessibles à l'aide du même jeton:
Avec des configurations séparées lorsque vous demandez
token
à un module chargé paresseusement, vous obtiendrezBService
exactement comme prévu.RouterModule utilise un
ROUTES
jeton pour obtenir toutes les routes spécifiques à un module. Puisqu'il veut que les routes spécifiques au module chargé paresseusement soient disponibles dans ce module (analogues à notre BService), il utilise une configuration différente pour les modules enfants chargés paresseusement:la source
forRoot
un module chargé différé créera de nouvelles instances de tous les services globaux dans l'injecteur de module chargé différé. Oui, cela conduira à des résultats imprévisibles. Lisez également cet article Éviter les confusions courantes avec les modules dans AngularJe pense que les réponses sont correctes mais je pense qu'il manque quelque chose.
La chose qui manque est "pourquoi et qu'est-ce que ça résout?".
OK commençons.
Commençons par mentionner quelques informations:
Tous les modules ont accès aux services racine.
Ainsi, même les modules chargés paresseusement peuvent utiliser un service fourni dans
app.module
.Que se passera-t-il si un module chargé paresseusement se fournira un service que le module d'application a déjà fourni? il y aura 2 instances.
Ce n'est pas un problème mais c'est parfois le cas .
Comment pouvons-nous le résoudre? N'importez simplement pas un module avec ce fournisseur dans des modules chargés différés.
Fin de l'histoire.
C'était juste pour montrer que les modules chargés différés ont leur propre point d'injection (par opposition aux modules non chargés différés).
Mais que se passe-t-il lorsqu'un module partagé (!) A été déclaré
providers
et que ce module est importé par lazy andapp.module
? Encore une fois, comme nous l'avons dit, deux cas.Alors, comment pouvons-nous résoudre cela dans le module partagé POV? Nous avons besoin d'un moyen de ne pas utiliser
providers:[]
! Pourquoi? car ils seront automatiquement importés à la fois dans la consommation paresseux et app.module et nous ne le voulons pas, car nous avons vu que chacun aura une instance différente.Eh bien, il s'avère que nous pouvons déclarer un module partagé qui n'aura pas
providers:[]
, mais fournira quand même des fournisseurs (désolé :))Comment? Comme ça :
Avis, pas de fournisseurs.
Mais
que se passera-t-il maintenant lorsque app.module importera le module partagé avec POV de service? RIEN.
que se passera-t-il maintenant lorsqu'un module paresseux importera le module partagé avec POV de service? RIEN.
Saisie du mécanisme manuel par convention:
Vous remarquerez que les fournisseurs sur les photos ont
service1
etservice2
Cela nous permet d'importer
service2
pour les modules chargés différés etservice1
pour les modules non différés. ( toux ... routeur .... toux )BTW, personne ne vous empêche d'appeler
forRoot
dans un module paresseux. mais vous aurez 2 instances car vousapp.module
devriez également le faire - alors ne le faites pas dans des modules paresseux.Aussi - si les
app.module
appelsforRoot
(et personne n'appelleforchild
) - c'est bien, mais l'injecteur racine n'aura queservice1
. (disponible pour toutes les applications)Alors pourquoi en avons-nous besoin? Je dirais :
C'est tout.
Eh bien - c'est caché dans la phrase ci-dessus ^
La convention (!!!) lui permet d'être singleton - ou pour être plus précis - si vous ne suivez pas la convention - vous n'obtiendrez PAS de singleton.
Ainsi, si vous ne chargez que
forRoot
dans leapp.module
, vous n'obtenez qu'une seule instance car vous ne devez l'appelerforRoot
que dans leapp.module
.BTW - à ce stade, vous pouvez oublier
forChild
. le module chargé paresseusement ne devrait pas / ne sera pas appeléforRoot
- vous êtes donc en sécurité dans le POV de singleton.forRoot et forChild ne sont pas un paquet incassable - c'est juste qu'il est inutile d'appeler Root qui ne sera évidemment chargé que dans
app.module
sans donner la possibilité de modules paresseux, d'avoir leurs propres services, sans créer de nouveaux services-qui-devraient-être -singleton.Cette convention vous donne une belle capacité appelée
forChild
- à consommer des "services uniquement pour les modules chargés paresseusement".Voici une démo Les fournisseurs de racine donnent des nombres positifs, les modules chargés paresseusement donnent des nombres négatifs.
la source
La documentation indique clairement quel est le but de cette distinction ici: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
Chaque application a exactement un point de départ (racine) avec lequel le service de routage principal doit être initialisé
forRoot
, tandis que les routes pour des fonctionnalités "enfants" particulières doivent être enregistrées en plus avecforChild
. Il est extrêmement utile pour les sous-modules et les modules chargés paresseusement qui n'ont pas à être chargés au démarrage de l'application, et comme @Harry Ninh l'a dit, on leur dit de réutiliser RouterService au lieu de l'enregistrement du nouveau service, ce qui peut provoquer une erreur d'exécution.la source
Si appRoutes contient le chemin vers diverses fonctions du site (admin crud, user crud, book crud) et que nous voulons les séparer, nous pourrions simplement le faire:
Et pour les itinéraires:
la source