navigate example angular router

angular - example - RouterModule.forRoot(RUTAS) vs RouterModule.forChild(RUTAS)



router.navigate angular 5 (4)

Creo que las respuestas son correctas, pero creo que falta algo.
Lo que falta es "¿por qué y qué resuelve?".
Vale, empecemos.

Primero mencionemos alguna información:

Todos los módulos tienen acceso a los servicios raíz.
Entonces, incluso los módulos con carga lenta pueden usar un servicio que se proporcionó en app.module .
¿Qué sucederá si un módulo con carga lenta se proporcionará 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 resolverlo? simplemente no importe un módulo con ese proveedor a módulos con carga lenta.

Fin de la historia.

Esto fue solo para mostrar que los módulos con carga diferida tienen su propio punto de inyección (en oposición a los módulos sin carga diferida).

Pero, ¿qué sucede cuando un módulo compartido (!) Ha declarado providers , y ese módulo es importado por lazy y app.module ? De nuevo, 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 al consumidor perezoso como a app.module y no queremos eso, ya que vimos que cada uno tendrá una instancia diferente.

Bueno, resulta que podemos declarar un módulo compartido que no tendrá providers:[] , pero aún así, proporcionará prodiversidad (lo siento :))

Cómo ? Me gusta esto :

Aviso, no hay proveedores.

Pero

  • ¿Qué pasará ahora cuando app.module importe el módulo compartido con POV de servicio? NADA.

  • ¿Qué pasará ahora cuando un módulo perezoso importará el módulo compartido con POV de servicio? NADA.

Entrar en el mecanismo manual por convención:

Notará que los proveedores en las imágenes tienen service1 y service2

Esto nos permite importar service2 para módulos con carga diferida y service1 para módulos sin retardo. ( tos ... enrutador ... tos )

Por cierto, nadie lo detiene para llamar a forRoot dentro de un módulo perezoso. pero tendrá 2 instancias porque app.module también debería hacerlo, así que no lo haga en módulos perezosos.

Además, si app.module llama a forRoot (y nadie llama a forchild ), está bien, pero el inyector raíz solo tendrá service1 . (disponible para todas las aplicaciones)

Entonces, ¿por qué lo necesitamos? Yo diría que :

Permite que un módulo compartido pueda dividir sus diferentes proveedores para usarlos con módulos ansiosos y módulos perezosos, a través de la convención forRoot y forChild . Repito: convención

Eso es.

ESPERE !! ni una palabra sobre singleton ?? Entonces, ¿por qué leo Singleton en todas partes?

Bueno, está oculto en la oración anterior ^

Permite que un módulo compartido pueda dividir sus diferentes proveedores para usarlos con módulos ansiosos y módulos perezosos, a través de forRoot y forChild .

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 app.module , solo obtiene una instancia porque solo debe llamar a forRoot en app.module .
Por cierto, en este punto puede olvidarse de forChild . el módulo con carga forRoot no debería / no llamará a forRoot , por lo que está a salvo 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 en app.module sin dar la capacidad de módulos perezosos, tener sus propios servicios, sin crear nuevos servicios, que- debería ser singleton.

Esta convención le brinda una buena capacidad llamada forChild : consumir "servicios solo para módulos con carga lenta".

Aquí hay una demostración Los proveedores raíz producen números positivos, los módulos con carga lenta producen números negativos.

¿Cuáles son las diferencias entre estos dos y cuáles son los casos de uso para cada uno?

Los docs no son exactamente útiles:

forRoot crea un módulo que contiene todas las directivas, las rutas dadas y el 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 vaga suposición 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.


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

Llame a Rooteo solo en el módulo de aplicación raíz, AppModule. Llamarlo en cualquier otro módulo, particularmente en un módulo con carga lenta, es contrario a la intención y es probable que produzca un error de tiempo de ejecución.

Recuerde importar el resultado; no lo agregue a ninguna otra lista de @NgModule.

Cada aplicación tiene exactamente un punto de partida (raíz) donde el servicio de enrutamiento principal debe inicializarse con forRoot , mientras que las rutas para características "secundarias" particulares deben registrarse adicionalmente con forChild . Es extremadamente útil para submódulos y módulos de carga lenta que no tienen que cargarse al inicio de la aplicación, y como dijo @Harry Ninh, se les dice que reutilicen RouterService en lugar de registrar el nuevo servicio, lo que puede causar un error de tiempo de ejecución.


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:

imports: [ BrowserModule, HttpModule, AppRoutingModule, RouterModule.forRoot(categoriesRoutes), RouterModule.forRoot(auteursRoutes), ],

Y para rutas:

const auteursRoutes:Routes=[ {path:''auteurs/ajouter'',component:CreerAuteurComponent}, ] const categoriesRoutes: Routes = [ {path:''categories/consulter'',component:ConsultercategoriesComponent}, {path:''categories/getsouscategoriesbyid/:id'',component:GetsouscategoriesbyIDComponent}, {path:''categories/ajout'',component:CreerCategorieComponent}, {path:''categories/:id'',component:ModifiercategorieComponent}, {path:''souscategories/ajout/:id'',component:AjoutersouscategorieComponent}, {path:''souscategories/lecture/:id1'',component:SouscategoriesComponent}, {path:''souscategories/modifier/:id1'',component:ModifiersupprimersouscategorieComponent}, {path:''uploadfile'',component:UploadfileComponent}, {path:''categories'',component:ConsultercategoriesComponent}, ]


Sugiero leer este artículo:

Módulo con proveedores

Cuando importa un módulo, generalmente usa una referencia a la clase de módulo:

@NgModule({ providers: [AService] }) export class A {} ----------------------------------- @NgModule({ imports: [A] }) export class B

De esta forma, 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:

@NgModule({ providers: [AService] }) class A {} export const moduleWithProviders = { ngModule: A, providers: [AService] }; ---------------------- @NgModule({ imports: [moduleWithProviders] }) export class B

Esto tiene las mismas implicaciones que la anterior.

Probablemente sepa que los módulos con carga lenta tienen su propio inyector. Supongamos que desea registrar AService para que esté disponible para toda la aplicación, pero algunos BService estarán disponibles para módulos con carga BService . Puede refactorizar su módulo de esta manera:

@NgModule({ providers: [AService] }) class A {} export const moduleWithProvidersForRoot = { ngModule: A, providers: [AService] }; export const moduleWithProvidersForChild = { ngModule: A, providers: [BService] }; ------------------------------------------ @NgModule({ imports: [moduleWithProvidersForRoot] }) export class B // lazy loaded module @NgModule({ imports: [moduleWithProvidersForChild] }) export class C

Ahora BService solo estará disponible para módulos secundarios con carga AService y AService estará disponible para toda la aplicación.

Puede reescribir lo anterior como un módulo exportado como este:

@NgModule({ providers: [AService] }) class A { forRoot() { return { ngModule: A, providers: [AService] } } forChild() { return { ngModule: A, providers: [BService] } } } -------------------------------------- @NgModule({ imports: [A.forRoot()] }) export class B // lazy loaded module @NgModule({ imports: [A.forChild()] }) export class C

¿Cómo es eso relevante para RouterModule?

Supongamos que se accede a ambos utilizando el mismo token:

export const moduleWithProvidersForRoot = { ngModule: A, providers: [{provide: token, useClass: AService}] }; export const moduleWithProvidersForChild = { ngModule: A, providers: [{provide: token, useClass: BService}] };

Con configuraciones separadas cuando solicita un token desde un módulo con carga BService obtendrá BService tal como estaba planeado.

RouterModule usa el token ROUTES 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:

static forChild(routes: Routes): ModuleWithProviders { return { ngModule: RouterModule, providers: [{provide: ROUTES, multi: true, useValue: routes}] }; }