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

gga*_*bor 53 angular-material2 angular

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

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

- MainModule
- SharedModule
- FeatureModuleA
    - FeatureModuleA1
    - FeatureModuleA2
- FeatureModuleB
Run Code Online (Sandbox Code Playgroud)

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

我应该如何定义FeatureModuleA以某种方式"转移".forRoot()函数?

@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 
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以为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 { }
Run Code Online (Sandbox Code Playgroud)

但是如何在这个特殊的ModuleClass中"转移".forRoot()调用?

正如我所见,我需要将所有子模块直接导入到我的根MainModule中,并为每个子模块调用.forRoot():

@NgModule({
  imports: [
    FeatureModuleA1.forRoot(),
    FeatureModuleA2.forRoot(),
    FeatureModuleA.forRoot(),
    SharedModule.forRoot()
  ]
})
class MainModule { }
Run Code Online (Sandbox Code Playgroud)

我对吗?在你回答之前,请看一下这个文件:https: //github.com/angular/material2/blob/master/src/lib/module.ts

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

Pau*_*tha 101

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

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

其理由是,如果添加AuthServiceproviders@NgModule,有可能为一个以上的被创建,如果您导入SharedModule到其他模块.

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

出于这个原因,我们添加一个(按惯例)forRoot方法来表示只应该为根(app)模块调用该方法,而对于其他模块,它应该只是正常导入

@NgModule({
  imports: [SharedModule]
})
class FeatureModule {}

@NgModule({
  imports: [SharedModule.forRoot()]
})
class AppModule {}
Run Code Online (Sandbox Code Playgroud)

  • forRoot只应用于app模块.不应该转发任何东西.在不使用forRoot的情况下导入Just SharedModule时,永远不会调用forRoot.我们应该这样构建我们的模块.forRoot中的应用程序范围的服务,以及NgModule中的所有其他服务.嵌套与否,这是你应该考虑的方式 (3认同)
  • 是! 我试着弄清楚那个!你检查了材料仓库的链接了吗?它们只是在"功能"模块中使用.forRoot()导入 - 并且还创建了一个特殊的MaterialRootModule来处理这种情况.BTW官方文档中没有关于此技术的任何信息.最后他们为我解决了我不需要导入并为每个子模块调用forRoot().所以我试着在我自己的项目中以某种方式解决同样的问题. (2认同)
  • 是的,但是你应该只在像他们制作根模块整合者的材料这样的情况下导入forRoot.如果该子模块用于其他模块,则不应将forRoot模块导入该子模块. (2认同)

小智 6

由于forRoot只打算提供集服务,你可以明确地“再提供”他们在SharedModule

@NgModule({})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [
        AuthService,
        FeatureModuleA.forRoot().providers,
        FeatureModuleB.forRoot().providers,
      ],
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,所有服务将由其SharedModule本身提供(而不是由相应的子模块提供),但这似乎无关紧要。也许有人可以争论...

注意,这FeatureModuleA也可以以类似的方式从其子模块“重新提供”单例服务。