您提供的链接中的要点是注册服务的所有不同方法,从最不具体到最具体。
特定应用 - 使用 @Injectable({ providedIn: 'root' })
当您在根级别提供服务时,Angular 会创建一个单独的、共享的 HeroService 实例,并将其注入到任何需要它的类中。在 @Injectable() 元数据中注册提供程序还允许 Angular 通过从已编译的应用程序中删除不使用的服务来优化应用程序。
模块特定 - 在模块提供程序中注册
当您向特定 NgModule 注册提供程序时,该 NgModule 中的所有组件都可以使用同一个服务实例。要在此级别注册,请使用 @NgModule() 装饰器的 providers 属性,
组件特定-在组件中注册
当您在组件级别注册提供程序时,您将获得一个新的服务实例以及该组件的每个新实例。在组件级别,在 @Component() 元数据的 providers 属性中注册一个服务提供者。
以上所有引用均来自官方Introduction to services and dependency injection页面
- 如果你只有一个模块,那么前两种方法是等价的,只需要使用一种方法。使用
@Injectable 更容易 - 默认的 CLI 方法。
- 如果要在多个模块之间共享服务实例,请使用第一种方法。
- 如果您希望每个独立模块一个实例,请使用第二种方法。
- 如果您想与除一个组件之外的所有组件共享一个应用范围的实例,那么除了对一个异常组件使用第三种方法之外,还使用第一种方法。
我认为大多数用例都属于前两种方法。
注册特定模块的服务
提示:只需使用providedIn: 'root'。如果由于摇晃树而未使用模块,则不会为模块编译未使用的服务。声明特定于模块的服务似乎是多余的,正如我们将看到的那样,可能会导致问题。
有两种方法可以注册特定模块的服务 - 从模块或从服务。
模块
@NgModule({
providers: [MyService]
})
export class MyModule {}
服务
@Injectable({ providedIn: MyModule })
后者是官方推荐的方法。声明提供者数组是早期的遗留物。
来自the docs:
上面的示例显示了在模块中提供服务的首选方式。这种方法是首选的,因为如果没有任何注入它,它会启用服务的 tree-shaking。如果无法在服务中指定应由哪个模块提供,您也可以在模块中为服务声明提供者
为什么你应该只使用providedIn: 'root'
所以我们看到这种方法是可摇树的。到目前为止,一切都很好。但是,如果您只是尝试导入与声明使用客户端的组件相同的模块,那么您最终会得到循环引用。
进行此设置:
我的模块
declarations: [
MyComponent
]
我的服务
@Injectable({ providedIn: MyModule })
我的组件
constructor(private myService: MyService) {}
- 我的服务导入我的模块
- 我的模块导入我的组件
- 我的组件导入我的服务
存在循环依赖。
解决方法是创建一个服务模块并将其导入到您的模块中。
我的模块
imports: [
MyModuleServices
],
declarations: [
MyComponent
]
我的模块服务
我的服务
@Injectable({ providedIn: MyModuleServices })
我的组件
constructor(private myService: MyService) {}
这是一个非常冗长的替代方案,而不是简单地使用 providedIn: 'root' 并让摇树来完成这项工作。