RouterModule.forRoot (ROUTES) 대 RouterModule.forChild (ROUTES)


111

이 둘의 차이점은 무엇이며 각각의 사용 사례는 무엇입니까?

문서는 정확하게 도움이되지 않습니다 :

forRoot는 모든 지시문, 지정된 경로 및 라우터 서비스 자체를 포함하는 모듈을 만듭니다.

forChild는 모든 지시문과 지정된 경로를 포함하지만 라우터 서비스는 포함하지 않는 모듈을 만듭니다.

내 모호한 추측은 하나는 '메인'모듈 용이고 다른 하나는 가져온 모듈 용이라는 것입니다 (메인 모듈에서 이미 서비스를 사용할 수 있기 때문에).하지만 실제로 사용 사례를 생각할 수 없습니다.


1
이해하지 못하는 것에 대해 좀 더 구체적으로 말씀해 주시겠습니까? 포함 된 인용문은 문자 그대로 차이점이 무엇인지 알려줍니다.
jonrsharpe

2
.forChild () 사용의 요점이 무엇인지 이해하지 못합니다. 서비스가없는 지시문과 경로는 언제 원합니까? 그동안 게시물에서 삭제 한 질문에 답해주세요 ...
VSO

18
하나가 있어야 RouterService하나 Angular2 응용 프로그램. forRoot반면, 해당 서비스를 초기화하고 어떤 경로 설정과 함께 DI에 등록 할 forChild경우에만 추가 경로 CONFIGS를 등록하고 재사용 할 수 Angular2을 말할 것이다 RouterServiceforRoot생성했습니다.
Harry Ninh 2011

@HarryNinh : 감사합니다-그게 제가 찾고 있던 것입니다. 초기 등록 이외의 추가 경로는 언제 등록하고 싶습니까? 좀 어리석은 것 같습니다. 동적으로 경로를 만들 수있는 방법이 없다고 생각합니다.
VSO 2011

1
앵귤러 라우터 작성자 빅터가 이것을 참조하십시오 .
nikhil mehta

답변:


123

이 기사를 읽는 것이 좋습니다.

공급자가있는 모듈

모듈을 가져올 때 일반적으로 모듈 클래스에 대한 참조를 사용합니다.

@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}]
    };
}

3
즉, forRoot ()가 이미 루트 모듈에서 호출되었고 필요한 모든 서비스가 추가 되었기 때문에 기능 모듈에서 forChild ()를 호출해야합니다. 그래서 forRoot ()를 다시 호출하면 예측할 수없는 상태가 될까요?
Wachburn 2010 년

7
@Wachburn, forRoot지연로드 된 모듈을 호출 하면 지연로드 된 모듈 인젝터에 모든 글로벌 서비스의 새 인스턴스가 생성됩니다. 예, 이것은 예측할 수없는 결과로 이어질 것입니다. 또한이 문서 읽기 각도에서 모듈과 공통의 혼란을 방지
최대 Koretskyi

1
@Willwsharp, 왜?
Max Koretskyi

1
나는 이것을 완전히 이해한다. 그러나 Routermodule.foRoot, VS Routermodule.forChild의 차이점은 무엇입니까? forRoot & forChild는 전달 된 값에 따라 개체를 반환하는 정적 메서드입니다. 그래서 app module에서 왜 forChild를 사용할 수 없습니까 ?? 왜 던지는 오류입니까? forRoot를 여러 개 사용할 수없는 이유는 무엇입니까?
Subhadeep

2
때로는 대답을 통해 요점으로 바로가는 것이 좋습니다. 정보 과부하는 대부분의 경우 더 많은 혼란을 초래합니다.
Adépòjù Olúwáségun

33

답은 맞다고 생각하지만 뭔가 빠진 것 같아요.
빠진 것은 "왜 그리고 무엇을 해결 하는가?"입니다.
그래 시작하자.

먼저 몇 가지 정보를 언급하겠습니다.

모든 모듈은 루트 서비스에 액세스 할 수 있습니다.
따라서 지연로드 된 모듈도 .NET에서 제공되는 서비스를 사용할 수 있습니다 app.module.
지연로드 된 모듈이 앱 모듈이 이미 제공 한 서비스를 자체적으로 제공하면 어떻게됩니까? 2 개의 인스턴스 가 있습니다 .
문제는 아니지만 때로는 문제 됩니다.
어떻게 해결할 수 있습니까? 그 공급자가있는 모듈을 지연로드 된 모듈로 가져 오지 마십시오.

이야기의 끝.

이 ^는 지연로드 된 모듈에 자체 주입 지점이 있음을 보여주기위한 것입니다 (지연로드되지 않은 모듈과 반대로).

그러나 shared (!) 모듈이 선언 providers되고 해당 모듈을 lazy app.module ? 다시 말했듯이 두 가지 경우가 있습니다.

그렇다면 공유 모듈 POV에서이 문제를 어떻게 해결할 수 있습니까? 사용 하지 않는 방법이 필요합니다 providers:[]! 왜? lazy와 app.module을 모두 사용하기 위해 자동으로 가져 오기 때문에 각기 다른 인스턴스를 갖게되는 것을 원하지 않습니다.

글쎄요, 우리가 가지고 있지 providers:[]않지만 여전히 공급자를 제공 할 공유 모듈을 선언 할 수 있다는 것이 밝혀졌습니다 (죄송합니다 :))

어떻게? 이렇게 :

여기에 이미지 설명 입력

통지, 공급자 없음.

그러나

  • app.module이 서비스 POV와 함께 공유 모듈을 가져올 때 어떤 일이 발생합니까? 아무것도.

  • 지연 모듈이 서비스 POV와 함께 공유 모듈을 가져올 때 이제 어떻게 될까요? 아무것도.

규칙을 통해 수동 메커니즘 입력 :

당신은 사진의 공급자가있는 것을 알 수 service1service2

이를 통해 service2지연로드 된 모듈과 service1지연되지 않은 모듈 을 가져올 수 있습니다 . ( 기침 ... 라우터 .... 기침 )

BTW, 아무도 forRootlazy 모듈 내 에서 호출 하는 것을 막지 않습니다 . 하지만 2 개의 인스턴스를 갖게 될 것입니다. 왜냐하면 app.module역시해야 하기 때문입니다. 그래서 지연 모듈 에서는하지 마십시오.

또한- app.module호출 하면 forRoot(아무도 호출하지 않음 forchild) 괜찮지 만 루트 인젝터는 service1. (모든 앱에서 사용 가능)

그렇다면 왜 필요합니까? 나는 말할 것이다 :

그것은 공유 모듈, 할 수 있도록 허용 분할 을 통해 - 열망 모듈과 게으른 모듈을 사용하기 위해 서로 다른 공급자 forRootforChild규칙을. 반복한다 : 컨벤션

그게 다야.

잠깐! 싱글 톤에 대해 한 마디도하지 않았나요 ?? 그래서 왜 어디서나 싱글 톤을 읽습니까?

글쎄-위의 문장에 숨겨져 있습니다 ^

공유 모듈이 forRoot 및 forChild 를 통해 eager 모듈 및 lazy 모듈과 함께 사용되도록 다른 공급자를 분할 할 수 있습니다 .

규칙 또는 더 정확하게하기 위해 - - 당신이 규칙을 따르지 않을 경우 - 당신은 것입니다 (!)가 싱글을 할 수 없습니다 싱글을 얻을.
당신은 단지로드한다면 forRoot으로 app.module 만 호출해야하기 때문에, 당신은 하나의 인스턴스를 가져 forRoot에서 그것을 app.module.
BTW-이 시점에서 잊을 수 있습니다 forChild. 지연로드 된 모듈은 호출하지 않아야 /하지 않을 것 forRoot입니다. 따라서 싱글 톤의 POV에서 안전합니다.

forRoot 및 forChild는 하나의 깨지지 않는 패키지가 아닙니다. 단지 app.module 지연 모듈에 대한 기능을 제공하지 않고서 만로드되는 Root를 호출 할 지점이 없으며 , 새로운 서비스를 생성하지 않고 자체 서비스를 갖습니다. -하나씩 일어나는 것.

이 규칙 forChild은 "지연로드 된 모듈에 대해서만 서비스"를 사용 하는 멋진 기능을 제공합니다 .

루트 공급자는 양수를 산출하고 지연로드 모듈은 음수를 산출합니다.


1. 여기서 POV는 무엇입니까? 2. stackblitz가 더 이상 작동하지 않습니다.
Nicholas K

@NicholasK이 stackblitz는 항상 잠시 후에 물건을 엉망으로 만듭니다. 새 버전을 업로드하려고합니다
Royi Namir

26

문서는 https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root 에서이 구분의 목적이 무엇인지 명확하게 설명합니다.

루트 애플리케이션 모듈 인 AppModule에서만 forRoot를 호출하십시오. 다른 모듈, 특히 지연로드 된 모듈에서이를 호출하는 것은 의도에 반하며 런타임 오류를 생성 할 가능성이 있습니다.

결과를 가져 오는 것을 잊지 마십시오. 다른 @NgModule 목록에 추가하지 마십시오.

모든 애플리케이션에는 기본 라우팅 서비스를로 초기화해야하는 시작 지점 (루트)이 정확히 하나 있으며 forRoot특정 "하위"기능에 대한 경로는에 추가로 등록해야합니다 forChild. 응용 프로그램 시작시로드 할 필요가없는 하위 모듈 및 지연로드 된 모듈에 매우 유용하며 @Harry Ninh이 말했듯이 새 서비스를 등록하는 대신 RouterService를 다시 사용하라는 메시지가 표시되어 런타임 오류가 발생할 수 있습니다.


2
해당 문서는 이동 된 것 같습니다. v2.angular.io/docs/ts/latest/guide/…
PeterS

1

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},



]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.