使用 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中。
我认为它是创建 CoreModule 的替代方案,文档明确指出:
在 Angular 中,有两种方法可以使服务成为单例: 为 @Injectable()providedIn 属性的值声明根
将服务包含在 AppModule 中或仅由 AppModule 导入的模块中
我在这里找到了这个单例服务文档
如果您的应用程序有一个纯服务的 CoreModule,您可以简单地摆脱它(当然,如果您认为没有必要),尽管我不推荐它,但对我来说,我认为拥有一个 CoreModule 更容易维护,因为我可以轻松地在项目中找到它,并告诉我哪些服务是应用程序的基础服务,我们只需要其中的一个实例,而不必在 IDE 中打开搜索对话框并查找具有
providedIn: 'root'
的所有服务已设置。
我仍然会为单例全局组件和 Http 拦截器保留 CoreModule,
providedIn
属性现在是注册单例服务的推荐方法,为了清楚起见,我会将所有单例服务放在 core/services 目录下
我认为创建核心模块已经过时了,因为服务可以定义自己通过
providedIn: root
注册到 root
(旧的!)角度风格指南建议在 v6 之前创建核心模块:https://v6.angular.io/guide/styleguide
但是从 v7 开始,不再建议创建核心模块。 我认为这正是出于这个原因(
providedIn: root
完成了这项工作)。
如果 CoreModule 仅包含服务,情况就是如此。然而,它确实包括其他东西,例如一次性组件。
来自 Angular 文档:
在 CoreModule 中收集应用程序范围内的一次性组件。当应用程序启动时将其导入一次(在 AppModule 中),并且永远不要将其导入到其他任何地方。 (例如 NavComponent 和 SpinnerComponent)。
那么拦截者和守卫呢?我猜这件事可能是全球性的。我同意你关于 CoreModule 没有声明而只有纯服务的考虑,但我认为 Guards 和 Interceptors 也应该考虑到。
当 Angular 引擎开始初始化组件,并且您在构造函数中声明了服务时,Angular 会尝试将声明的服务的实例传递给组件。所以 Angular 应该以某种方式知道在哪里可以获取实例,有一个点就是提供者数组出现的地方。
当您在没有提供的情况下声明所需的服务时:核心对,我们将创建该服务的非单例实例。这意味着,当 Angular 销毁组件时,组件中声明的服务也会被销毁。
如前所述,声明应用级单例服务有两种方法: 1. 将其声明为相关模块的提供者; 2. 使用providIn:核心对将它们声明为组件的提供者。
还有关于 @Injectable 装饰器的有趣注释。仅当服务注入另一个服务时才需要这样做。例如,如果您在服务中注入http服务,则必须添加@Injecrable装饰器。
这就是依赖注入的工作原理。
providedIn: 'root'
是声明式方式core module
是命令式如果您需要有条件地注入提供程序,很容易在模块内完成,并且
core module
是为您的应用程序导入每项必需服务的那个。例如,这对于根据环境变量导入测试或生产服务非常有用。
如果您的服务只有一个版本,那么
providedIn: 'root'
是一个不错的选择。
provideIn: root
这在您拥有多应用程序项目的情况下可能很有用。在这种情况下,您有一个有角度的工作空间,其中包含多个项目。
并且,您永远不会希望您的项目对工作区的
core module
有某种依赖关系,因为它不允许您独立运行您的项目。
在这种情况下,您将服务保留在库中并使用
providedIn: 'root'
使它们成为单例。