我在一个项目上工作,遇到了一个没有@注入()装饰器的服务,它工作得很好。到目前为止,我的印象是,在角度上,如果我们想实现DI我们必须使用@注入()装饰器并与提供者一起配置它。使用提供者配置服务是强制性的,但使用@注入()装饰器似乎不是。它只在某些服务中使用。我在使用装饰器的服务和不使用装饰器的服务中注意到的唯一区别是前者本身有一些依赖项,而后者没有
我有两种服务:
类型1:
export class SharedService {
//do something
}
类型2:
@Injectable()
export class MainCreditService {
constructor(private http: Http, private config: Config) {
this.config.EndPoints.subscribe(endpointObj => {
this.environment = endpointObj;
});
}
app. module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule, ReactiveFormsModule} from '@angular/forms';
import { HttpClientModule} from '@angular/common/http'
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule,
],
exports: [],
providers: [MainService,SharedService],
bootstrap: [AppComponent]
})
export class AppModule { }
app组件
import { Component } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { MainService } from '../../services/main.service';
import { SharedService } from '../../services/shared.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private mainservice: MainService, private sharedService:
SharedService) {
//doSomething
}
为什么一个人需要@注入()而另一个不需要
我在DI上看了一些视频,浏览了一些文章,但仍然很难理解我们应该在哪里使用这个装饰器以及为什么。有人能解释一下这个装饰器的目的吗,或者粘贴链接到解释得很好的来源。
是的,你是对的,我们可以创建一个没有注入()装饰器的服务。那我们为什么需要这个?
可注入装饰器或任何其他角度/自定义装饰器生成元数据。注入服务需要一种特殊的元数据(设计:参数类型)。
没有依赖关系和没有可注入:
@Component({
selector: 'ponyracer-app',
template: '<h1>PonyRacer</h1>'
})
export class PonyRacerAppComponent {
constructor(private appService: AppService) {
console.log(appService);
}
}
// without Injectable
export class AppService {
constructor() {
console.log('new app service');
}
}
从留档:https://angular.io/guide/dependency-injection
通过在以下三个位置之一设置元数据值,您可以在应用的不同级别使用提供程序配置注入器:
>
在服务本身的@Inject table()装饰器中。
在NgModule的@NgModule()装饰器中。
在组件的@Component()装饰器中。
@Injecttable()装饰器具有ProvidedIn元数据选项,您可以在其中使用根注入器或特定NgModule的注入器指定装饰服务类的提供者。
要使用具有DI的类,它必须有一个提供者,而@Inject table()装饰器是注册提供者的一种方式。
如果您使用@Inject table()
,您不必显式地将MyServiceClass添加到模块或组件的提供者属性中。
在总结中@Injecttable()不是强制性的,因为它只是定义提供者的另一种方式。同样,如果您将@Injecttable({ProvidedIn:'root'})
添加到您的服务中,您将不需要将服务添加到任何模块或组件上的任何提供者
属性。
假设您有一个组件:
@Component({
selector: "service-tester",
templateUrl: "./service-tester.component.html",
styleUrls: ["./service-tester.component.css"],
providers: [ProvidedByComponentService]
})
export class ServiceTesterComponent {
constructor(
public componentService: ProvidedByComponentService,
public rootService: ProvidedByRootService
) {}
}
它注入两个服务:一个在根级别,另一个在组件中提供。
如果我们查看我们的服务,他们会做同样的事情:
export class ProvidedByComponentService {
public clickCount: BehaviorSubject<number>;
constructor() {
this.clickCount = new BehaviorSubject<number>(0);
}
increment() {
this.clickCount.next(this.clickCount.value + 1);
}
}
唯一的区别是根中提供的服务有一个装饰器:
@Injectable({ providedIn: "root" })
export class ProvidedByRootService {
// same as previous service, code omitted for brevity.
}
现在这些服务之间的唯一区别是当一个新的时,提供者将创建多少实例
这意味着当Provideo dByRootService
中的计数递增时,它将在每个ServiceTesterComponent
中递增,而Provideo dByComponentService
中的计数只会在该组件的本地递增
这允许您根据服务是否可以是单例以灵活的方式声明提供者。
服务(例如API服务)是可以从根中提供的服务中受益的良好示例,因为它们通常不保存任何状态,或者保存与整个应用程序相关的状态。
下面示例的Stackblitz:
https://stackblitz.com/edit/angular-ivy-jboftq?file=src/app/service-tester/service-tester.component.ts
可注入()装饰器用于将其他服务或对象注入到您的服务中。
如果你的服务没有任何依赖关系,那么你不需要添加注入()装饰器。但是如果你的服务有一些依赖关系,那么你必须添加注入()装饰器,否则角度将无法在你的服务中注入依赖关系,这将引发运行时错误。
您有两个服务,一个带有Injecttable()装饰器,另一个没有Injecttable()。
您会注意到MainCreditService具有Injecttable()装饰器,并且它在构造函数中具有一些依赖项,即私有超文本传输协议:Http,私有配置:Config。但是SharedService没有Injecttable()装饰器,它也没有依赖项。
export class SharedService {
//do something
}
@Injectable()
export class MainCreditService {
constructor(private http: Http, private config: Config) {
this.config.EndPoints.subscribe(endpointObj => {
this.environment = endpointObj;
});