Angular document说,在模块级别声明的提供程序对整个应用程序可见:
自举模块的@ NgModule.providers中列出的提供程序具有应用程序范围。将服务提供商添加到@ NgModule.providers可以有效地将服务发布到整个应用程序。
因此,这意味着可以将来自模块(AAAModule
)的服务注入到另一个模块(BBBModule
)中。但是,其他Angular document说我们可以通过在@NgModule
声明提供者来将提供者的范围限制为特定模块:
您可以使用非根NgModule的providerIn元数据选项在模块级别配置提供程序,以将提供程序的范围限制为该模块。
以同样的方式,another document说,我们可以将提供者的范围限制为特定的组件:
NgModule中的各个组件具有自己的注入器。通过使用@Component元数据在组件级别配置提供程序,可以将提供程序的范围限制为组件及其子级。
那是什么事实?如果我在模块级别声明了提供程序,那么它对整个应用程序还是模块可见? “范围”仅意味着提供者的“生命周期”?
答案 0 :(得分:1)
我认为,在您的理解中,导致您困惑的缺失部分是Angular的lazy loading feature。延迟加载的模块将具有自己的注入器(但从根注入器继承)。因此,延迟加载的模块中列出的提供程序将被限制在该模块的范围内,并且仅在映射到该模块的路由上存在。
将模块导入到其他模块(不是延迟加载)时,这些模块中列出的所有提供程序都将合并到同一注入器中。这些提供者将在整个应用程序生命周期中存活。
组件中列出的提供者将仅在该组件中存在。例如,考虑一个列出提供者且位于*ngIf
内且可以切换的组件。创建组件后,即同时创建了提供程序。当组件被破坏时,提供者也将被破坏。该提供程序只能在该组件和任何组件/指令及其列出的提供程序中访问,它们是DOM树的后代。
请考虑以下示例:
模块A已导入AppModule
模块B延迟加载
到目前为止,我只讨论了模块文件中列出的提供程序。然后是使用providedIn
in the @Injectable
decorator的最新约定(从Angular 6开始)。我建议您看看this article。虽然本文讨论了在模块中列出提供程序的旧方法与使用providedIn
的新方法,但我认为这可能有助于您了解提供程序的可用范围。
答案 1 :(得分:0)
自举模块的@ NgModule.providers中列出的提供程序具有应用程序范围。将服务提供商添加到@ NgModule.providers可以有效地将服务发布到整个应用程序。
如果您在根模块装饰器providers
数组中声明提供程序,则是,范围是整个应用程序。它与根注入器相关联,从而使整个应用程序中具有相同的单例实例。如果在功能模块中声明了提供者,则除非导入了该模块,否则该提供者将不可用。但是,如果在 根模块 中声明,则它随处可见。
您可以使用非根NgModule的providerIn元数据选项在模块级别配置提供程序,以将提供程序的范围限制为该模块。
如果使用@Injectable
并在providedIn
属性中提及提供者的范围,则只有那些导入声明了服务的模块的模块才能获取该实例。这样就可以进行树状摇动,从本质上讲,这意味着将提供程序代码从最终捆绑包中排除(如果未在应用程序中使用它)。
对于延迟加载的模块,将创建根注入器的另一个子代,该子代复制根注入器以及在延迟模块中声明的提供者的所有内容。在延迟加载组件的情况下,提供者是从此子注入器注入的,而不是从根注入器注入的。
NgModule中的各个组件具有自己的注入器。您 可以通过以下方式将提供者的范围限制为组件及其子组件 使用@Component在组件级别配置提供程序 元数据。
在这种情况下,每个组件都将获取自己的提供者副本,并且与根注入器中配置的实例不同。当您需要不想在各个组件之间共享的提供者的私有副本时,请执行此操作。