有人能向我澄清一下,我应该如何用.forRoot()
调用构建多个嵌套的功能模块层次结构吗?
例如,如果我有这样的模块:
- MainModule
- SharedModule
- FeatureModuleA
- FeatureModuleA1
- FeatureModuleA2
- FeatureModuleB
所有功能模块都具有.forRoot()
静态功能。
我应该如何定义FeatureModuleA;转移";CCD_ 3的功能?
@NgModule({
imports: [
//- I can use .forRoot() calls here but this module not the root module
//- I don't need to import sub-modules here, FeatureA only a wrapper
//FeatureModuleA1.forRoot(), //WRONG!
//FeatureModuleA2.forRoot(), //WRONG!
],
exports: [
//I cannot use .forRoot() calls here
FeatureModuleA1,
FeatureModuleA2
]
})
class FeatureModuleA {
static forRoot(): ModuleWithProviders {
return {
//At this point I can set any other class than FeatureModuleA for root
//So lets create a FeatureRootModuleA class: see below!
ngModule: FeatureModuleA //should be: FeatureRootModuleA
};
}
}
我可以为root用户创建另一个类,然后在FeatureModuleA:的forRoot()
函数中设置它
@NgModule({
imports: [
//Still don't need any sub module within this feature module
]
exports: [
//Still cannot use .forRoot() calls but still need to export them for root module too:
FeatureModuleA1,
FeatureModuleA2
]
})
class FeatureRootModuleA { }
但是我怎么能";转移";
.forRoot()
调用这个特殊的ModuleClass?
正如我所看到的,我需要将所有子模块直接导入到我的根MainModule中,并为每个模块调用.forRoot()
:
@NgModule({
imports: [
FeatureModuleA1.forRoot(),
FeatureModuleA2.forRoot(),
FeatureModuleA.forRoot(),
SharedModule.forRoot()
]
})
class MainModule { }
我说得对吗?在回答之前,请查看此文件:https://github.com/angular/material2/blob/master/src/lib/module.ts
据我所知,此回购由官方angular团队维护。因此,他们只需在一个特殊的MaterialRootModule模块中导入所有.forRoot()
调用即可解决上述问题。我真的不明白它将如何应用于我自己的根模块?根和.forRoot在这里的真正含义是什么?这是相对于软件包而不是实际的web项目吗?
通常forRoot
用于添加应用程序/单例服务。
@NgModule({
providers: [ /* DONT ADD HERE */ ]
})
class SharedModule {
static forRoot() {
return {
ngModule: SharedModule,
providers: [ AuthService ]
}
}
}
理由是,如果将AuthService
添加到@NgModule
中的providers
,则如果将SharedModule
导入其他模块,则可能会创建多个。
当SharedModule
被导入到一个急切加载的模块中时,我并不100%清楚是否会创建服务,但所提到的文档的解释是关于延迟加载的模块。当您懒洋洋地加载一个模块时,将创建所有的提供程序。
出于这个原因,我们添加了一个(按惯例(forRoot
方法,表示该方法只应为根(应用程序(模块调用,而对于其他模块,则应正常导入
@NgModule({
imports: [SharedModule]
})
class FeatureModule {}
@NgModule({
imports: [SharedModule.forRoot()]
})
class AppModule {}
由于forRoot
仅用于提供单例服务,您可以在SharedModule
:中显式地"重新提供"它们
@NgModule({})
class SharedModule {
static forRoot() {
return {
ngModule: SharedModule,
providers: [
AuthService,
FeatureModuleA.forRoot().providers,
FeatureModuleB.forRoot().providers,
],
}
}
}
这样,所有服务都将由SharedModule
本身提供(而不是由相应的子模块提供(,但这似乎无关紧要。也许有人会争论。。。
注意,FeatureModuleA
也可以以类似的方式从其子模块"重新提供"单例服务。
如上所述,延迟加载模块很重要,因为共享服务可以在延迟加载模块中使用,但如果该服务已经被另一个模块使用并实例化,那么将有两个实例,因此需要使用singleton模式。AuthService就是一个很好的例子——你不想让一个服务实例的用户未经身份验证,而另一个实例的用户"相同"。
Angular 6新增了一种将提供者注册为单例的新方法。在服务的@Injectable((装饰器中,使用providedIn属性。将其值设置为"root"。然后,您不需要将其添加到根模块的提供者列表中,或者在这种情况下,您也可以将其设置为SharedModule,如下所示:
@Injectable({
providedIn: SharedModule // or 'root' for singleton
})
export class AuthService {
...