62

谁能向我澄清一下我应该如何通过.forRoot()调用来构建多个嵌套的功能模块层次结构?

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

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

所有功能模块都具有.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 
    };
  }
}

我可以为 root 使用创建另一个类,然后在forRoot()FeatureModuleA 的函数中设置它:

@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

据我所知,这个 repo 是由官方 Angular 团队维护的。.forRoot()所以他们通过在一个特殊的 MaterialRootModule 模块中导入所有调用来解决上述问题。我真的不明白它将如何应用于我自己的根模块?root.forRoot在这里的真正含义是什么?这是相对于包而不是实际的网络项目?

4

3 回答 3

108

一般forRoot用于添加应用程序/单例服务。

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

原因是,如果在中添加AuthService,如果将 导入其他模块,则可能会创建多个。providers@NgModuleSharedModule

我不是 100% 清楚是否会在将服务SharedModule导入急切加载的模块时创建服务,但文档提到的解释是关于延迟加载的模块。当你延迟加载一个模块时,所有的提供者都会被创建。

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

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

@NgModule({
  imports: [SharedModule.forRoot()]
})
class AppModule {}
于 2016-09-23T06:17:35.227 回答
10

forRoot仅用于提供单例服务,您可以在以下位置显式“重新提供”它们SharedModule

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

这样所有的服务都将由它SharedModule自己提供(而不是由各自的子模块),但似乎没关系。也许有人可以争论...

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

于 2018-04-05T10:07:53.723 回答
1

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

Angular 6 新增了一种将提供者注册为单例的新方法。在服务的 @Injectable() 装饰器中,使用 providedIn 属性。将其值设置为“根”。然后你不需要将它添加到根模块的提供者列表中,或者在这种情况下你也可以像这样将它设置到你的 SharedModule 中:

@Injectable({
  providedIn: SharedModule // or 'root' for singleton
})
export class AuthService {
...
于 2018-06-08T14:28:53.560 回答