我强烈建议阅读这篇文章:
提供者模块
当你导入一个模块时,你通常使用对模块类的引用:
@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}]
};
}