¿Cuáles son las diferencias entre estos dos y cuáles son los casos de uso para cada uno?
Los documentos no son exactamente útiles:
forRoot crea un módulo que contiene todas las directivas, las rutas dadas y el propio servicio del enrutador.
forChild crea un módulo que contiene todas las directivas y las rutas dadas, pero no incluye el servicio de enrutador.
Mi conjetura vaga es que uno es para el módulo 'principal' y el otro es para cualquier módulo importado (ya que ya tendrían el servicio disponible desde el módulo principal), pero realmente no puedo pensar en un caso de uso.
RouterService
para una sola aplicación Angular2.forRoot
Inicializará ese servicio y lo registrará en DI junto con alguna configuración de ruta, mientrasforChild
que solo registrará configuraciones de ruta adicionales y le dirá a Angular2 que reutilice elRouterService
queforRoot
ha creado.Respuestas:
Recomiendo encarecidamente leer este artículo:
Módulo con proveedores
Cuando importa un módulo, generalmente usa una referencia a la clase del módulo:
De esta manera, todos los proveedores registrados en el módulo
A
se agregarán al inyector raíz y estarán disponibles para toda la aplicación.Pero hay otra forma de registrar un módulo con proveedores como este:
Esto tiene las mismas implicaciones que el anterior.
Probablemente sepa que los módulos de carga diferida tienen su propio inyector. Entonces, suponga que desea registrarse
AService
para estar disponible para toda la aplicación, pero algunosBService
para estar disponibles solo para módulos cargados de forma diferida. Puede refactorizar su módulo de esta manera:Ahora
BService
solo estará disponible para los módulos de carga diferida para niños yAService
estará disponible para toda la aplicación.Puede reescribir lo anterior como un módulo exportado como este:
¿Qué importancia tiene eso para RouterModule?
Supongamos que se accede a ambos utilizando el mismo token:
Con configuraciones separadas cuando lo solicita
token
desde un módulo cargado de forma diferida, obtendráBService
tal como estaba planeado.RouterModule usa
ROUTES
token para obtener todas las rutas específicas de un módulo. Dado que quiere que las rutas específicas del módulo de carga diferida estén disponibles dentro de este módulo (análogos a nuestro BService), utiliza una configuración diferente para los módulos secundarios de carga diferida:fuente
forRoot
a un módulo de carga diferida creará nuevas instancias de todos los servicios globales en el inyector de módulo de carga diferida. Sí, esto dará lugar a resultados impredecibles. Lea también este artículo Evitar confusiones comunes con módulos en AngularCreo que las respuestas son correctas, pero creo que falta algo.
Lo que falta es "¿por qué y qué resuelve?".
Vale, empecemos.
Primero mencionemos algo de información:
Todos los módulos tienen acceso a los servicios raíz.
Por lo tanto, incluso los módulos con carga diferida pueden usar un servicio que se proporcionó en
app.module
.¿Qué pasará si un módulo de carga diferida se proporciona a sí mismo un servicio que el módulo de la aplicación ya proporcionó? habrá 2 instancias.
No es un problema, pero a veces lo es .
¿Cómo podemos solucionarlo? simplemente no importe un módulo con ese proveedor a módulos con carga diferida.
Fin de la historia.
Esto ^ fue solo para mostrar que los módulos con carga diferida tienen su propio punto de inyección (a diferencia de los módulos sin carga diferida).
Pero, ¿qué sucede cuando se ha declarado un módulo compartido (!)
providers
Y ese módulo es importado por lazy yapp.module
? Nuevamente, como dijimos, dos instancias.Entonces, ¿cómo podemos resolver esto en el módulo compartido POV? ¡Necesitamos una forma de no usar
providers:[]
! ¿Por qué? porque se importarán automáticamente tanto a lazy consumidor como a app.module y no queremos eso, ya que vimos que cada una tendrá una instancia diferente.Bueno, resulta que podemos declarar un módulo compartido que no tendrá
providers:[]
, pero aún así, proporcionará proveedores (lo siento :))¿Cómo? Me gusta esto :
Aviso, no hay proveedores.
Pero
¿Qué pasará ahora cuando app.module importe el módulo compartido con el punto de vista del servicio? NADA.
¿Qué pasará ahora cuando un módulo perezoso importará el módulo compartido con el punto de vista del servicio? NADA.
Ingresando al mecanismo manual a través de la convención:
Notará que los proveedores en las imágenes tienen
service1
yservice2
Esto nos permite importar
service2
para módulos con carga diferida y módulosservice1
no diferidos. ( tos ... enrutador ... tos )Por cierto, nadie te detiene para llamar
forRoot
dentro de un módulo perezoso. pero tendrá 2 instancias porqueapp.module
también debería hacerlo, así que no lo haga en módulos perezosos.Además, si
app.module
llamaforRoot
(y nadie llamaforchild
), está bien, pero el inyector raíz solo tendráservice1
. (disponible para todas las aplicaciones)Entonces, ¿por qué lo necesitamos? Yo diria :
Eso es.
Bueno, está escondido en la oración anterior ^
La convención (!!!) permite que sea singleton, o para ser más preciso, si no sigue la convención, NO obtendrá un singleton.
Entonces, si solo carga
forRoot
en elapp.module
, entonces obtiene solo una instancia porque solo debe llamarloforRoot
en elapp.module
.Por cierto, en este punto puedes olvidarte
forChild
. el módulo de carga diferida no debería / no llamaráforRoot
, por lo que está seguro en POV de singleton.forRoot y forChild no son un paquete irrompible, es solo que no tiene sentido llamar a Root, que obviamente se cargará solo
app.module
sin dar la capacidad a los módulos perezosos, tener sus propios servicios, sin crear nuevos servicios, que deberían ser -único.Esta convención le da una buena habilidad llamada
forChild
- consumir "servicios sólo para módulos cargados de forma diferida".Aquí hay una demostración Los proveedores raíz producen números positivos, los módulos cargados de forma diferida producen números negativos.
fuente
La documentación establece claramente cuál es el propósito de esta distinción aquí: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
Cada aplicación tiene exactamente un punto de partida (raíz) donde se debe inicializar el servicio de enrutamiento principal
forRoot
, mientras que las rutas para funciones "secundarias" particulares deben registrarse adicionalmente conforChild
. Es extremadamente útil para submódulos y módulos de carga diferida que no tienen que cargarse al inicio de la aplicación, y como dijo @Harry Ninh, se les dice que reutilicen RouterService en lugar del registro del nuevo servicio, lo que puede causar un error de tiempo de ejecución.fuente
Si appRoutes contiene una ruta a varias funciones en el sitio (admin crud, user crud, book crud) y queremos separarlas, simplemente podríamos hacer eso:
Y para rutas:
fuente