当在Angular CLI中生成服务时,它会为Injectable装饰器添加一个'provided in'属性(默认值为'root')的额外元数据。
@Injectable({
providedIn: 'root',
})
providedIn到底做什么?我假设这是使服务可用的像一个“全局”类型的单例服务的整个应用程序,然而,不会更干净地在AppModule的提供者数组中声明这样的服务?
当在Angular CLI中生成服务时,它会为Injectable装饰器添加一个'provided in'属性(默认值为'root')的额外元数据。
@Injectable({
providedIn: 'root',
})
providedIn到底做什么?我假设这是使服务可用的像一个“全局”类型的单例服务的整个应用程序,然而,不会更干净地在AppModule的提供者数组中声明这样的服务?
当前回答
自Angular 6以来,providedIn: 'root'是最简单、最有效的提供服务的方法:
该服务将作为单例在整个应用范围内可用,不需要将其添加到模块的providers数组中(如Angular <= 5)。 如果服务只在一个惰性加载的模块中使用,那么该模块也会被惰性加载 如果它从未被使用过,它将不会包含在构建中(摇树)。
欲了解更多信息,请阅读文档和NgModule faq
Btw:
如果你不想要应用范围的单例,可以使用组件的提供者数组。 如果你想限制作用域,让其他开发人员无法在特定模块之外使用你的服务,可以使用NgModule的providers数组。
其他回答
如果使用providedIn,可注入对象被注册为模块的提供者,而不需要将其添加到模块的提供者中。
从文档
服务本身是CLI生成的一个类 用@Injectable装饰。默认情况下,配置了这个装饰器 使用providedIn属性,该属性为服务创建提供者。 在这种情况下,providedIn: 'root'指定服务应该是 在根注入器中提供。
@Nipuna的精彩解释,
我想通过添加例子来扩展它。
如果你只使用Injectable装饰器而不使用providedin属性,比如,
@Injectable()
那么你必须在相应模块的providers数组中写入服务的名称。
像这样;
data.service.ts↴
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
constructor() {}
// Code . . .
}
app.module.ts↴
import { AppComponent } from './app.component';
import { DataService } from './core/data.service';
@NgModule({
declarations: [AppComponent],
providers: [DataService], // ⟵ LOOK HERE WE PROVIDED IT
imports: [...],
bootstrap: [AppComponent],
})
export class AppModule {}
但是,如果你使用providedIn: 'root',就像这样:
data.service.ts↴
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
constructor() {}
// Code . . .
}
然后我们的模块看起来像这样:
app.module.ts↴
import { AppComponent } from './app.component';
import { DataService } from './core/data.service';
@NgModule({
declarations: [AppComponent],
providers: [],
imports: [...],
bootstrap: [AppComponent],
})
export class AppModule {}
看,这次我没有在providers数组中添加DataService,因为它不需要。
良好的实践
在Angular指南中,这可能会派上用场
Do provide a service with the app root injector in the @Injectable decorator of the service. Why? The Angular injector is hierarchical. Why? When you provide the service to a root injector, that instance of the service is shared and available in every class that needs the service. This is ideal when a service is sharing methods or state. Why? When you register a service in the @Injectable decorator of the service, optimization tools such as those used by the Angular CLI's production builds can perform tree shaking and remove services that aren't used by your app. Why? This is not ideal when two different components need different instances of a service. In this scenario it would be better to provide the service at the component level that needs the new and separate instance.
providedIn告诉Angular,根注入器负责创建你的服务的实例。以这种方式提供的服务将自动提供给整个应用程序,不需要在任何模块中列出。
服务类可以充当它们自己的提供者,这就是为什么在@Injectable装饰器中定义它们就是你所需要的全部注册。
根据文档:
在@Injectable()元数据中注册提供者也是允许的 Angular通过从编译后的 应用程序,如果它没有使用。
简单. .
providedIn:'root'为整个应用程序创建了一个实例,而不需要从任何NgModule中提供它。只需通过@Injectable装饰器在服务中声明即可。
如果您希望为任何组件拥有该服务的一个新实例,那么可以通过组件的提供程序声明它。这将为该组件及其子组件(如果有的话)创建另一个新实例。因此,您可以有一个具有全局作用域的实例和一个组件的另一个实例。