@Injectable()装饰器和提供者数组

时间:2020-02-24 13:51:15

标签: angular dependency-injection angular-services angular-module

@Injectable()装饰器中“根”中提供的服务是否仍必须位于模块的providers数组中?

Angular documentation并没有真正给我答案,或者我不太理解。

在我的核心文件夹中,我有一个身份验证服务,该服务以root身份提供。为了使用所有提供的服务和组件,我不会将我的核心模块导入应用模块。

我是否必须在模块的providers数组中另外设置服务,还是已经使用装饰器在根级别提供了足够的服务?

2 个答案:

答案 0 :(得分:2)

您提供的链接中的要点是注册服务的所有不同方法,从最不具体到最具体。

特定于应用程序-使用@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 })

后者是官方推荐的方法。声明providers数组是早期的宿醉。

来自the docs

以上示例显示了在模块中提供服务的首选方式。此方法是首选方法,因为如果没有注入,它将启用服务的树状摇动。如果无法在服务中指定应由哪个模块提供服务,则还可以在模块内声明服务的提供者

为什么您应该只使用providedIn: 'root'

因此,我们看到这种方法可以摇树。到现在为止还挺好。但是,如果仅尝试导入声明使用客户端的组件的模块,则最终将得到循环引用。

进行此设置:

我的模块

declarations: [
  MyComponent
]

我的服务

@Injectable({ providedIn: MyModule })

我的组件

constructor(private myService: MyService) {}
  • my-service导入my-module
  • my-module导入my-component
  • my-component导入my-service

存在循环依赖项。

解决方法是创建一个服务模块并将其导入到您的模块中。

我的模块

imports: [
  MyModuleServices
],
declarations: [
  MyComponent
]

my-module-services


我的服务

@Injectable({ providedIn: MyModuleServices })

我的组件

constructor(private myService: MyService) {}

这是一个非常漫长的选择,而不是简单地使用providedIn: 'root'并让树摇晃来做。

答案 1 :(得分:1)

执行@Injectable()中“根”中提供的服务 装饰器仍必须位于模块的providers数组中吗?

不!

当您使用Angular CLI创建服务时,我相信默认情况下会添加providedIn: "root",因此从技术上讲,您永远不需要将自己的服务添加到provider数组中。

我是否还必须在的提供商数组中另外设置服务 模块,还是已经在根级别提供了足够的模块 使用装饰器?

使用装饰器在根级别提供它就足够了。

但是,并非我创建的所有服务都旨在成为全局服务。创建服务时,将配置对象删除到@Injectable()元数据的情况并不罕见,该服务将在单个屏幕或子模块之间共享-而不是在整个应用程序中共享。在这种情况下,我会必须将该服务添加到使用该服务或子模块声明的各个组件上的providers数组中。