【问题标题】:Angular 6 Services: providedIn: 'root' vs CoreModuleAngular 6 服务:providedIn:'root' vs CoreModule
【发布时间】:2018-11-24 10:23:08
【问题描述】:

对于 Angular 6,以下是创建单例服务的首选方式:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

来自 Angular 文档: 当你在根级别提供服务时,Angular 会创建一个单一的、共享的 HeroService 实例,并注入到任何需要它的类中。在 @Injectable 元数据中注册提供程序还允许 Angular 通过删除服务来优化应用程序,如果它根本没有被使用。

还有,

providers: [
    // no need to place any providers due to the `providedIn` flag...
  ]

那么,这是否意味着我们不再需要CoreModule?我们可以将服务和其他常用模块直接导入到 AppModule 中。

【问题讨论】:

  • 看起来是的,它对我来说可能已经过时了,但是我们在哪里保留所有服务呢?在名为“coreServices”的根文件夹中:)

标签: angular angular6


【解决方案1】:
  • providedIn: 'root' 是声明方式
  • core module 是命令式的方式

如果您需要有条件地注入提供程序,很容易在一个模块中完成,core module 是为您的应用程序导入所有强制性服务的那个。例如,这对于根据环境变量导入测试或生产服务很有用。

如果您的服务只有一个版本,那么providedIn: 'root' 是一个不错的选择。

【讨论】:

    【解决方案2】:

    provideIn: root 这在您有多个应用程序项目的情况下可能很有用。在这种情况下,您有一个角度工作区,其中包含多个项目。

    而且,您永远不会希望您的项目对工作区的 core module 有某种依赖关系,因为它不允许您独立运行您的项目。

    在这种情况下,您将服务保存在库中并使用providedIn: 'root' 将它们设为单例。

    【讨论】:

      【解决方案3】:

      我认为创建核心模块已经过时了,因为服务可以将自己定义为通过 providedIn: root 注册到 root

      建议在 v6 之前创建核心模块的(旧的!)角度风格指南:https://v6.angular.io/guide/styleguide

      但从 v7 开始,不再推荐创建核心模块。 我认为正是出于这个原因(providedIn: root 完成了这项工作)。

      【讨论】:

        【解决方案4】:

        当 Angular 引擎启动一个组件,并且你在构造函数中声明了服务时,Angular 会尝试将声明的服务的实例传递给组件。所以 Angular 应该以某种方式知道可以在哪里获取实例,提供者数组的来源是一个点。

        当您声明所需的服务而没有提供:核心对时,我们会创建该服务的非单例实例。也就是说,当 Angular 销毁组件时,组件中声明的服务也会被销毁。

        如前所述,应用级单例服务有两种声明方式: 1. 声明为相关模块的提供者; 2. 使用providedIn: 核心对将它们声明为组件的提供者。

        还有关于@Injectable 装饰器的有趣说明。这仅在服务注入另一个服务时才需要。例如,如果您在服务中注入 http 服务,则必须添加 @Injecrable 装饰器。

        这就是依赖注入的工作原理。

        【讨论】:

          【解决方案5】:

          好吧,我认为它是创建 CoreModule 的替代方案,文档明确指出:

          在 Angular 中有两种方法可以使服务成为单例: 为 @Injectable() providedIn 属性的值声明根

          将服务包含在 AppModule 中或仅由 AppModule 导入的模块中

          我在这里找到了这个Singleton Services doc

          如果你的应用程序有一个纯服务的 CoreModule,你可以简单地摆脱它(如果你认为当然没有必要),虽然我不推荐它,但对我来说,我认为拥有一个更易于维护CoreModule,因为我可以很容易地在项目中找到它并告诉我哪些服务是应用程序的基础,我们只需要它们中的一个实例,而不必在 IDE 中打开搜索对话框并查找具有 @ 的所有服务987654322@已设置。

          【讨论】:

          • 在模块中提供服务的首选方式是使用“providedIn”。首选此方法,因为如果没有注入服务,它会启用服务的摇树。
          【解决方案6】:

          我仍然会将 CoreModule 用于一次性组件和 Http 拦截器,现在推荐使用 providedIn 属性注册单例服务,为了清楚起见,我会将所有单例服务放在 core/services 目录下

          【讨论】:

          【解决方案7】:

          那么拦截器和守卫呢?我猜这件事可能是全球性的。我同意你对 CoreModule 没有声明只有纯服务的考虑,但我认为 Guards 和 Interceptors 也应该考虑周到。

          【讨论】:

          • 完全同意你的观点:CoreModule 是唯一适合 Guards 和 Interceptors 的模块,因为它们只需要提供一次。
          • @dave0688 但是你也可以在守卫和拦截器上使用providedIn: 'root'。这也使它们可摇树,而将它们添加到 CoreModule 则否定它们可摇树。这就是为什么 Angular 推荐 providedIn: 'root'
          【解决方案8】:

          如果 CoreModule 仅包含服务,那将是真的。但是,它确实包括其他东西,例如一次性组件。

          来自 Angular 文档:

          在 CoreModule 中收集应用程序范围内的一次性组件。应用程序启动时导入一次(在 AppModule 中),永远不要在其他任何地方导入它。 (例如 NavComponent 和 SpinnerComponent)。

          【讨论】:

          • 关于在核心模块中放置组件仍然存在争议。 Documentation also state that: "考虑让 CoreModule 成为一个没有声明的纯服务模块。"
          • 一次性组件是指仅在您的 AppComponent 模板中使用的组件,在其他任何地方都没有,对吧?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-21
          • 2020-05-10
          • 2020-04-04
          • 1970-01-01
          • 2023-03-27
          • 2018-10-17
          相关资源
          最近更新 更多