@Injectable()装饰器中“根”中提供的服务是否仍必须位于模块的providers数组中?
Angular documentation并没有真正给我答案,或者我不太理解。
在我的核心文件夹中,我有一个身份验证服务,该服务以root身份提供。为了使用所有提供的服务和组件,我不会将我的核心模块导入应用模块。
我是否必须在模块的providers数组中另外设置服务,还是已经使用装饰器在根级别提供了足够的服务?
答案 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) {}
存在循环依赖项。
解决方法是创建一个服务模块并将其导入到您的模块中。
我的模块
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数组中。