ฉันขอแนะนำให้อ่านบทความนี้:
โมดูลกับผู้ให้บริการ
เมื่อคุณนำเข้าโมดูลคุณมักจะใช้การอ้างอิงไปยังคลาสโมดูล:
@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
จะพร้อมใช้งานสำหรับโมดูลที่โหลดแบบขี้เกียจเท่านั้น คุณสามารถ refactor โมดูลของคุณได้ดังนี้:
@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
โทเค็นเพื่อรับเส้นทางทั้งหมดที่เฉพาะเจาะจงไปยังโมดูล เนื่องจากต้องการให้มีเส้นทางเฉพาะสำหรับโมดูลที่โหลดแบบ lazy เพื่อให้พร้อมใช้งานภายในโมดูลนี้ (อะนาล็อกกับ BService ของเรา) จึงใช้การกำหนดค่าที่แตกต่างกันสำหรับโมดูลลูกที่โหลดแบบ lazy:
static forChild(routes: Routes): ModuleWithProviders {
return {
ngModule: RouterModule,
providers: [{provide: ROUTES, multi: true, useValue: routes}]
};
}