功能模块的提供程序是否随处可见?

时间:2019-02-04 02:03:05

标签: angular

Angular document说,在模块级别声明的提供程序对整个应用程序可见:

  

自举模块的@ NgModule.providers中列出的提供程序具有应用程序范围。将服务提供商添加到@ NgModule.providers可以有效地将服务发布到整个应用程序。

因此,这意味着可以将来自模块(AAAModule)的服务注入到另一个模块(BBBModule)中。但是,其他Angular document说我们可以通过在@NgModule声明提供者来将提供者的范围限制为特定模块:

  

您可以使用非根NgModule的providerIn元数据选项在模块级别配置提供程序,以将提供程序的范围限制为该模块。

以同样的方式,another document说,我们可以将提供者的范围限制为特定的组件:

  

NgModule中的各个组件具有自己的注入器。通过使用@Component元数据在组件级别配置提供程序,可以将提供程序的范围限制为组件及其子级。

那是什么事实?如果我在模块级别声明了提供程序,那么它对整个应用程序还是模块可见? “范围”仅意味着提供者的“生命周期”?

2 个答案:

答案 0 :(得分:1)

我认为,在您的理解中,导致您困惑的缺失部分是Angular的lazy loading feature。延迟加载的模块将具有自己的注入器(但从根注入器继承)。因此,延迟加载的模块中列出的提供程序将被限制在该模块的范围内,并且仅在映射到该模块的路由上存在。

将模块导入到其他模块(不是延迟加载)时,这些模块中列出的所有提供程序都将合并到同一注入器中。这些提供者将在整个应用程序生命周期中存活。

组件中列出的提供者将仅在该组件中存在。例如,考虑一个列出提供者且位于*ngIf内且可以切换的组件。创建组件后,即同时创建了提供程序。当组件被破坏时,提供者也将被破坏。该提供程序只能在该组件和任何组件/指令及其列出的提供程序中访问,它们是DOM树的后代。

请考虑以下示例:

  • 模块A已导入AppModule

    • 模块A中列出的提供者位于根注入器中。这意味着该提供程序可在整个应用程序中使用,并且在应用程序的整个生命周期中都可以使用。
  • 模块B延迟加载

    • 已创建子注入器。模块B中列出的提供者或导入到模块B中的任何模块中列出的提供者都将驻留在该新注射器中。

到目前为止,我只讨论了模块文件中列出的提供程序。然后是使用providedIn in the @Injectable decorator的最新约定(从Angular 6开始)。我建议您看看this article。虽然本文讨论了在模块中列出提供程序的旧方法与使用providedIn的新方法,但我认为这可能有助于您了解提供程序的可用范围。

答案 1 :(得分:0)

  

自举模块的@ NgModule.providers中列出的提供程序具有应用程序范围。将服务提供商添加到@ NgModule.providers可以有效地将服务发布到整个应用程序。

如果您在根模块装饰器providers数组中声明提供程序,则是,范围是整个应用程序。它与根注入器相关联,从而使整个应用程序中具有相同的单例实例。如果在功能模块中声明了提供者,则除非导入了该模块,否则该提供者将不可用。但是,如果在 根模块 中声明,则它随处可见。

  

您可以使用非根NgModule的providerIn元数据选项在模块级别配置提供程序,以将提供程序的范围限制为该模块。

如果使用@Injectable并在providedIn属性中提及提供者的范围,则只有那些导入声明了服务的模块的模块才能获取该实例。这样就可以进行树状摇动,从本质上讲,这意味着将提供程序代码从最终捆绑包中排除(如果未在应用程序中使用它)。

对于延迟加载的模块,将创建根注入器的另一个子代,该子代复制根注入器以及在延迟模块中声明的提供者的所有内容。在延迟加载组件的情况下,提供者是从此子注入器注入的,而不是从根注入器注入的。

  

NgModule中的各个组件具有自己的注入器。您   可以通过以下方式将提供者的范围限制为组件及其子组件   使用@Component在组件级别配置提供程序   元数据。

在这种情况下,每个组件都将获取自己的提供者副本,并且与根注入器中配置的实例不同。当您需要不想在各个组件之间共享的提供者的私有副本时,请执行此操作。