如何在要素模块层次结构中使用.forRoot()

时间:2016-09-23 05:17:13

标签: angular angular-material2

任何人都可以向我澄清我应该如何使用.forRoot()调用构建多个嵌套的功能模块层次结构?

例如,如果我有这样的模块:

- MainModule
- SharedModule
- FeatureModuleA
    - FeatureModuleA1
    - FeatureModuleA2
- FeatureModuleB

所有要素模块都具有.forRoot()静态函数。

如何以某种方式“转移”.forRoot()函数来定义 FeatureModuleA

@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

我知道这个由官方角度团队维护的回购。因此,他们只需在特殊的MaterialRootModule模块中导入所有.forRoot()调用即可解决上述问题。我真的不明白它将如何应用于我自己的根模块? root .forRoot 在这里真正意味着什么?这是相对于包而不是实际的Web项目吗?

3 个答案:

答案 0 :(得分:97)

通常forRoot用于添加应用程序/单例服务。

@NgModule({
  providers: [ /* DONT ADD HERE */ ]
})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [ AuthService ]
    }
  }
}

原因是,如果您将AuthService添加到providers中的@NgModule,则可以导入多个SharedModule来导入SharedModule 1}}进入其他模块。

我不是100%清楚当forRoot被导入到一个急切加载的模块时是否会创建服务,但是文档提到的解释是关于延迟加载的模块。当您懒洋洋地加载模块时,将创建所有提供程序。

出于这个原因,我们添加了一个(按惯例)@NgModule({ imports: [SharedModule] }) class FeatureModule {} @NgModule({ imports: [SharedModule.forRoot()] }) class AppModule {} 方法来表示只应为根(app)模块调用该方法,而对于其他模块,它应该只是正常导入

pd.to_datetime(df['hour'], unit='h')

答案 1 :(得分:4)

由于SharedModule仅用于提供单件服务,您可以在@NgModule({}) class SharedModule { static forRoot() { return { ngModule: SharedModule, providers: [ AuthService, FeatureModuleA.forRoot().providers, FeatureModuleB.forRoot().providers, ], } } } 中明确“重新提供”这些服务:

SharedModule

这样,所有服务都将由FeatureModuleA本身(而不是相应的子模块)提供,但似乎并不重要。也许有人可以争辩......

请注意,{{1}}也可以以类似的方式从子模块“重新提供”单件服务。

答案 2 :(得分:1)

如上所述,延迟加载的模块很重要,因为共享服务可以在延迟加载的模块中使用,但如果该服务已经被另一个模块使用和实例化,那么将有两个实例因此需要单身模式。 AuthService就是一个很好的例子 - 你不希望有一个未经身份验证的用户拥有该服务的一个实例,而另一个拥有"相同的"用户已通过身份验证。

Angular 6的新功能有一种将提供程序注册为单例的新方法。在服务的@Injectable()装饰器中,使用providedIn属性。将其值设置为' root'。然后您不需要将它添加到根模块的提供者列表中,或者在这种情况下,您也可以将它设置为您的SharedModule,如下所示:

@Injectable({
  providedIn: SharedModule // or 'root' for singleton
})
export class AuthService {
...