在Angular 6中生成服务时,使用Injectable装饰器提供的目的是什么?

时间:2018-06-14 01:22:52

标签: angular angular6

在Angular CLI中生成服务时,它会添加带有'provided in'属性的额外元数据,默认值为'root',用于Injectable装饰器。

@Injectable({
  providedIn: 'root',
})

究竟提供了什么?我假设这使得服务可用作整个应用程序的“全局”类型单例服务,但是,在AppModule的提供者数组中声明此类服务会不会更清晰?

更新

对于其他任何人,以下段落也提供了另一个很好的解释,特别是如果您想要仅为功能模块提供服务。

  

现在有一种新的,推荐的方式直接注册提供商   在@Injectable()装饰器中,使用新的providedIn   属性。它接受'root'作为您的价值或任何模块   应用。当您使用'root'时,您的injectable将成为。{1}}   在应用程序中注册为单例,您不需要   将其添加到根模块的提供程序。同样,如果你使用   providedIn: UsersModuleinjectable注册为   UsersModule的提供商,但未将其添加到providers   模块。“ -   https://blog.ninja-squad.com/2018/05/04/what-is-new-angular-6/

更新2:

经过进一步调查后,我认为只有providedIn: 'root'

才有用

如果你想在根模块以外的任何模块中provide服务,那么你最好在功能模块的装饰器中使用providers数组,否则你会受到循环依赖的困扰。这里有趣的讨论 - https://github.com/angular/angular-cli/issues/10170

6 个答案:

答案 0 :(得分:22)

如果使用providedIn,则注入为Module的提供者,而不将其添加到模块的提供者。

来自Docs

  

服务本身是CLI生成的类   用@Injectable装饰。默认情况下,配置此装饰器   使用providedIn属性,该属性为服务创建提供程序。   在这种情况下,提供:' root'指定服务应该是   在根注入器中提供。

答案 1 :(得分:11)

providedIn: 'root'是自Angular 6以来提供服务最简单,最有效的方法:

  1. 该服务将在应用程序范围内以单例形式提供,而无需将其添加到模块的provider数组中(例如Angular <= 5)。
  2. 如果该服务仅在延迟加载的模块中使用,它将与该模块一起延迟加载
  3. 如果从不使用它,它将不会包含在构建中(摇晃的树)。

有关更多信息,请考虑阅读documentationNgModule FAQs

顺便说一句:

  1. 如果您不希望应用程序范围内的单例,请改用提供程序的组件数组。
  2. 如果您想限制范围,以便没有其他开发人员可以在特定模块之外使用您的服务,请改为使用提供程序的NgModule数组。

答案 2 :(得分:4)

providedIn告诉Angular根注入器负责创建您的Service实例。通过这种方式提供的服务会自动提供给整个应用程序使用,不需要在任何模块中列出。

服务类可以充当其自己的提供程序,这就是为什么在@Injectable装饰器中定义它们是您所需的全部注册。

答案 3 :(得分:3)

请参阅@Nipuna的出色解释,

我想通过添加示例来扩展它。

如果您仅使用不带providedin属性的Injectable装饰器,例如

@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 {}

看到我这次没有在DataService数组中添加providers,因为不需要。

答案 4 :(得分:1)

根据Documentation

  

在@Injectable()元数据中注册提供者也可以   Angular通过从已编译的服务中删除服务来优化应用程序   应用程序(如果未使用)。

答案 5 :(得分:0)

来自文档

  

什么是可注射装饰器?

将一个类标记为可用于Injector进行创建。

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

服务本身是CLI生成的类,并用@Injectable()装饰。

  

provideIn到底能做什么?

通过将其与@NgModule或其他InjectorType关联,或通过指定应在“根”注入器中提供此注入物来确定将提供可注射物的注入器,在大多数应用程序中它将是应用程序级注入器

providedIn: Type<any> | 'root' | null
  

providedIn:“ root”

当您在根级别提供服务时,Angular会创建一个共享的服务实例,并将其注入到任何需要该服务的类中。在@Injectable()元数据中注册提供程序还允许Angular通过从未编译的应用程序中删除服务来优化应用程序。

  

providedIn:模块

也可以指定在特定的@NgModule中提供服务。例如,如果您不希望应用程序使用服务,除非它们导入您创建的模块,则可以指定应在模块中提供服务

import { Injectable } from '@angular/core';
import { UserModule } from './user.module';

@Injectable({
  providedIn: UserModule,
})
export class UserService {
}

首选此方法,因为如果没有注入,它可以使服务摇树。

如果无法在服务中指定哪个模块应提供该服务,则还可以在模块内声明该服务的提供者:

import { NgModule } from '@angular/core';
import { UserService } from './user.service';

@NgModule({
  providers: [UserService],
})
export class UserModule {
}