Quais são as diferenças entre os dois e quais são os casos de uso de cada um?
Os documentos não são exatamente úteis:
forRoot cria um módulo que contém todas as diretivas, as rotas fornecidas e o próprio serviço do roteador.
forChild cria um módulo que contém todas as diretivas e as rotas fornecidas, mas não inclui o serviço de roteador.
Meu palpite vago é que um é para o módulo 'principal' e o outro é para quaisquer módulos importados (uma vez que eles já teriam o serviço disponível no módulo principal), mas não consigo realmente pensar em um caso de uso.
RouterService
para um único aplicativo Angular2.forRoot
irá inicializar esse serviço e registrá-lo no DI junto com alguma configuração de rota, enquantoforChild
apenas registrará configurações de rota adicionais e dirá ao Angular2 para reutilizar oRouterService
queforRoot
criou.Respostas:
Eu sugiro fortemente a leitura deste artigo:
Módulo com provedores
Ao importar um módulo, você geralmente usa uma referência à classe do módulo:
Desta forma, todos os provedores registrados no módulo
A
serão adicionados ao injetor raiz e disponíveis para toda a aplicação.Mas há outra maneira de registrar um módulo com provedores como este:
Isso tem as mesmas implicações que o anterior.
Você provavelmente sabe que os módulos carregados lentamente têm seu próprio injetor. Portanto, suponha que você queira se registrar
AService
para ficar disponível para todo o aplicativo, mas algunsBService
para ficar disponível apenas para módulos carregados lentamente. Você pode refatorar seu módulo assim:Agora
BService
estará disponível apenas para módulos filhos carregados lentamente eAService
para todo o aplicativo.Você pode reescrever o acima como um módulo exportado como este:
Como isso é relevante para o RouterModule?
Suponha que ambos sejam acessados usando o mesmo token:
Com configurações separadas, quando você solicitar
token
de um módulo de carregamento lento, você obteráBService
exatamente como planejado.RouterModule usa
ROUTES
token para obter todas as rotas específicas para um módulo. Uma vez que ele deseja que rotas específicas para o módulo carregado lentamente estejam disponíveis dentro deste módulo (análogos ao nosso BService), ele usa uma configuração diferente para os módulos filhos carregados lentamente:fonte
forRoot
um módulo de carregamento lento criará novas instâncias de todos os serviços globais no injetor de módulo de carregamento lento. Sim, isso levará a resultados imprevisíveis. Leia também este artigo Evitando confusões comuns com módulos no AngularAcho que as respostas estão certas, mas acho que falta algo.
O que falta é "por que e o que isso resolve?".
OK vamos começar.
Primeiro, vamos mencionar algumas informações:
Todos os módulos têm acesso aos serviços raiz.
Assim, mesmo os módulos carregados lentamente podem usar um serviço que foi fornecido em
app.module
.O que acontecerá se um módulo de carregamento lento fornecer a si mesmo um serviço que o módulo de aplicativo já forneceu? haverá 2 instâncias.
Não é um problema, mas às vezes é .
Como podemos resolver isso ? simplesmente não importe um módulo com esse provedor para módulos carregados lentamente.
Fim da história.
Este ^ era apenas para mostrar que os módulos carregados lentamente têm seu próprio ponto de injeção (em oposição aos módulos carregados não lentamente).
Mas o que acontece quando um módulo compartilhado (!) É declarado
providers
e esse módulo é importado por lazy eapp.module
? Novamente, como dissemos, duas instâncias.Então, como podemos resolver isso no módulo POV compartilhado? Precisamos de uma maneira de não usar
providers:[]
! Por quê? porque eles serão importados automaticamente para consumir lazy e app.module e não queremos isso, pois vimos que cada um terá uma instância diferente.Bem, acontece que podemos declarar um módulo compartilhado que não terá
providers:[]
, mas ainda fornecerá provedores (desculpe :))Quão? Como isso :
Observe, nenhum provedor.
Mas
o que acontecerá agora quando app.module importará o módulo compartilhado com POV de serviço? NADA.
o que acontecerá agora quando um módulo preguiçoso importará o módulo compartilhado com POV de serviço? NADA.
Entrando no mecanismo manual via convenção:
Você notará que os provedores nas fotos têm
service1
eservice2
Isso nos permite importar
service2
módulos carregados lentamente e módulosservice1
não lazy. ( tosse ... roteador .... tosse )BTW, ninguém está impedindo você de ligar
forRoot
em um módulo preguiçoso. mas você terá 2 instâncias porqueapp.module
também deve fazê-lo - portanto , não o faça em módulos preguiçosos.Além disso - se
app.module
ligarforRoot
(e ninguém ligarforchild
) - tudo bem, mas o injetor root só teráservice1
. (disponível para todos os aplicativos)Então, por que precisamos disso? Eu diria :
É isso aí.
Bem - está escondido na frase acima ^
A convenção (!!!) permite que seja um singleton - ou para ser mais preciso - se você não seguir a convenção - você NÃO receberá um singleton.
Portanto, se você carregar apenas
forRoot
noapp.module
, obterá apenas uma instância, pois só deve chamá-forRoot
la noapp.module
.BTW - neste ponto você pode esquecer
forChild
. o módulo de carregamento lento não deve / não chamaforRoot
- então você está seguro no POV do singleton.forRoot e forChild não são um pacote inquebrável - é só que não adianta chamar o Root que obviamente será carregado apenas
app.module
sem dar a capacidade de módulos preguiçosos, ter seus próprios serviços, sem criar novos serviços que deveriam ser -singleton.Esta convenção oferece uma boa capacidade chamada
forChild
- para consumir "serviços apenas para módulos carregados lentamente".Aqui está uma demonstração que os provedores de raiz geram números positivos, os módulos carregados lentamente geram números negativos.
fonte
A documentação afirma claramente qual é o propósito desta distinção aqui: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
Cada aplicativo tem exatamente um ponto de partida (raiz) onde o serviço de roteamento principal deve ser inicializado
forRoot
, enquanto as rotas para recursos "filhos" específicos devem ser registradas adicionalmenteforChild
. É extremamente útil para submódulos e módulos carregados lentamente que não precisam ser carregados no início do aplicativo e, como @Harry Ninh disse, eles são instruídos a reutilizar RouterService em vez de registrar o novo serviço, o que pode causar um erro de execução.fonte
Se appRoutes contiver o caminho para várias funções no site (admin crud, user crud, book crud) e quisermos separá-los, poderíamos simplesmente fazer isso:
E para rotas:
fonte