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