[angular] RouterModule.forRoot (ROUTES) 대 RouterModule.forChild (ROUTES)
이 둘의 차이점은 무엇이며 각각의 사용 사례는 무엇입니까?
문서는 정확하게 도움이되지 않습니다 :
forRoot는 모든 지시문, 지정된 경로 및 라우터 서비스 자체를 포함하는 모듈을 만듭니다.
forChild는 모든 지시문과 지정된 경로를 포함하지만 라우터 서비스는 포함하지 않는 모듈을 만듭니다.
내 모호한 추측은 하나는 ‘메인’모듈 용이고 다른 하나는 가져온 모듈 용이라는 것입니다 (메인 모듈에서 이미 서비스를 사용할 수 있기 때문에).하지만 실제로 사용 사례를 생각할 수 없습니다.
답변
이 기사를 읽는 것이 좋습니다.
공급자가있는 모듈
모듈을 가져올 때 일반적으로 모듈 클래스에 대한 참조를 사용합니다.
@NgModule({
providers: [AService]
})
export class A {}
-----------------------------------
@NgModule({
imports: [A]
})
export class B
이렇게하면 모듈에 등록 된 모든 공급자 A
가 루트 인젝터에 추가되고 전체 애플리케이션에서 사용할 수 있습니다.
그러나 다음과 같은 공급자에 모듈을 등록하는 또 다른 방법이 있습니다.
@NgModule({
providers: [AService]
})
class A {}
export const moduleWithProviders = {
ngModule: A,
providers: [AService]
};
----------------------
@NgModule({
imports: [moduleWithProviders]
})
export class B
이것은 이전 것과 동일한 의미를 갖습니다.
지연로드 된 모듈에는 자체 인젝터가 있다는 것을 알고있을 것입니다. 따라서 AService
전체 응용 프로그램에서 사용할 수 있도록 등록 하고 일부 BService
는 지연로드 된 모듈에서만 사용할 수 있도록 등록하려고한다고 가정합니다 . 다음과 같이 모듈을 리팩터링 할 수 있습니다.
@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
이제는 BService
하위 지연로드 모듈에서만 사용할 수 AService
있으며 전체 애플리케이션에서 사용할 수 있습니다.
위의 내용을 다음과 같이 내 보낸 모듈로 다시 작성할 수 있습니다.
@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
RouterModule과 어떤 관련이 있습니까?
둘 다 동일한 토큰을 사용하여 액세스한다고 가정합니다.
export const moduleWithProvidersForRoot = {
ngModule: A,
providers: [{provide: token, useClass: AService}]
};
export const moduleWithProvidersForChild = {
ngModule: A,
providers: [{provide: token, useClass: BService}]
};
token
지연로드 된 모듈에서 요청할 때 별도의 구성을 사용하면 BService
계획대로 얻을 수 있습니다.
RouterModule은 ROUTES
토큰을 사용 하여 모듈에 특정한 모든 경로를 가져옵니다. 지연로드 된 모듈에 특정한 경로를이 모듈 (BService에 대한 아날로그) 내에서 사용할 수 있기를 원하기 때문에 지연로드 된 하위 모듈에 대해 다른 구성을 사용합니다.
static forChild(routes: Routes): ModuleWithProviders {
return {
ngModule: RouterModule,
providers: [{provide: ROUTES, multi: true, useValue: routes}]
};
}
답변
답은 맞다고 생각하지만 뭔가 빠진 것 같아요.
빠진 것은 “왜 그리고 무엇을 해결 하는가?”입니다.
그래 시작하자.
먼저 몇 가지 정보를 언급하겠습니다.
모든 모듈은 루트 서비스에 액세스 할 수 있습니다.
따라서 지연로드 된 모듈도 .NET에서 제공되는 서비스를 사용할 수 있습니다 app.module
.
지연로드 된 모듈이 앱 모듈이 이미 제공 한 서비스를 자체적으로 제공하면 어떻게됩니까? 2 개의 인스턴스 가 있습니다 .
문제는 아니지만 때로는 문제 가 됩니다.
어떻게 해결할 수 있습니까? 그 공급자가있는 모듈을 지연로드 된 모듈로 가져 오지 마십시오.
이야기의 끝.
이 ^는 지연로드 된 모듈에 자체 주입 지점이 있음을 보여주기위한 것입니다 (지연로드되지 않은 모듈과 반대로).
그러나 shared (!) 모듈이 선언 providers
되고 해당 모듈을 lazy 및 app.module
? 다시 말했듯이 두 가지 경우가 있습니다.
그렇다면 공유 모듈 POV에서이 문제를 어떻게 해결할 수 있습니까? 사용 하지 않는 방법이 필요합니다 providers:[]
! 왜? lazy와 app.module을 모두 사용하기 위해 자동으로 가져 오기 때문에 각기 다른 인스턴스를 갖게되는 것을 원하지 않습니다.
글쎄요, 우리가 가지고 있지 providers:[]
않지만 여전히 공급자를 제공 할 공유 모듈을 선언 할 수 있다는 것이 밝혀졌습니다 (죄송합니다 :))
어떻게? 이렇게 :
통지, 공급자 없음.
그러나
-
app.module이 서비스 POV와 함께 공유 모듈을 가져올 때 어떤 일이 발생합니까? 아무것도.
-
지연 모듈이 서비스 POV와 함께 공유 모듈을 가져올 때 이제 어떻게 될까요? 아무것도.
규칙을 통해 수동 메커니즘 입력 :
당신은 사진의 공급자가있는 것을 알 수 service1
및service2
이를 통해 service2
지연로드 된 모듈과 service1
지연되지 않은 모듈 을 가져올 수 있습니다 . ( 기침 … 라우터 …. 기침 )
BTW, 아무도 forRoot
lazy 모듈 내 에서 호출 하는 것을 막지 않습니다 . 하지만 2 개의 인스턴스를 갖게 될 것입니다. 왜냐하면 app.module
역시해야 하기 때문입니다. 그래서 지연 모듈 에서는하지 마십시오.
또한- app.module
호출 하면 forRoot
(아무도 호출하지 않음 forchild
) 괜찮지 만 루트 인젝터는 service1
. (모든 앱에서 사용 가능)
그렇다면 왜 필요합니까? 나는 말할 것이다 :
그것은 공유 모듈, 할 수 있도록 허용 분할 을 통해 – 열망 모듈과 게으른 모듈을 사용하기 위해 서로 다른 공급자
forRoot
와forChild
규칙을. 반복한다 : 컨벤션
그게 다야.
잠깐! 싱글 톤에 대해 한 마디도하지 않았나요 ?? 그래서 왜 어디서나 싱글 톤을 읽습니까?
글쎄-위의 문장에 숨겨져 있습니다 ^
공유 모듈이 forRoot 및 forChild 를 통해 eager 모듈 및 lazy 모듈과 함께 사용되도록 다른 공급자를 분할 할 수 있습니다 .
규칙 또는 더 정확하게하기 위해 – – 당신이 규칙을 따르지 않을 경우 – 당신은 것입니다 (!)가 싱글을 할 수 없습니다 싱글을 얻을.
당신은 단지로드한다면 forRoot
으로 app.module
만 호출해야하기 때문에, 당신은 하나의 인스턴스를 가져 forRoot
에서 그것을 app.module
.
BTW-이 시점에서 잊을 수 있습니다 forChild
. 지연로드 된 모듈은 호출하지 않아야 /하지 않을 것 forRoot
입니다. 따라서 싱글 톤의 POV에서 안전합니다.
forRoot 및 forChild는 하나의 깨지지 않는 패키지가 아닙니다. 단지 app.module
지연 모듈에 대한 기능을 제공하지 않고서 만로드되는 Root를 호출 할 지점이 없으며 , 새로운 서비스를 생성하지 않고 자체 서비스를 갖습니다. -하나씩 일어나는 것.
이 규칙 forChild
은 “지연로드 된 모듈에 대해서만 서비스”를 사용 하는 멋진 기능을 제공합니다 .
답변
문서는 https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root 에서이 구분의 목적이 무엇인지 명확하게 설명합니다.
루트 애플리케이션 모듈 인 AppModule에서만 forRoot를 호출하십시오. 다른 모듈, 특히 지연로드 된 모듈에서이를 호출하는 것은 의도에 반하며 런타임 오류를 생성 할 가능성이 있습니다.
결과를 가져 오는 것을 잊지 마십시오. 다른 @NgModule 목록에 추가하지 마십시오.
모든 애플리케이션에는 기본 라우팅 서비스를로 초기화해야하는 시작 지점 (루트)이 정확히 하나 있으며 forRoot
특정 “하위”기능에 대한 경로는에 추가로 등록해야합니다 forChild
. 응용 프로그램 시작시로드 할 필요가없는 하위 모듈 및 지연로드 된 모듈에 매우 유용하며 @Harry Ninh이 말했듯이 새 서비스를 등록하는 대신 RouterService를 다시 사용하라는 메시지가 표시되어 런타임 오류가 발생할 수 있습니다.
답변
appRoutes에 사이트의 다양한 기능 (admin crud, user crud, book crud)에 대한 경로가 포함되어 있고 이들을 분리하려면 간단히 다음과 같이 할 수 있습니다.
imports: [
BrowserModule, HttpModule,
AppRoutingModule,
RouterModule.forRoot(categoriesRoutes),
RouterModule.forRoot(auteursRoutes),
],
그리고 경로 :
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},
]