typescript - Deklarera tjänsteinstans i konstruktorn i Angular 2
Jag är ny på Angular 2 och Typescript och försöker förstå DI. I all kod jag har sett ser jag att variabeln som hänvisar till en tjänst är typad i konstruktören. Varför är det så? Varför kan vi inte ha den deklarerad utanför konstruktören men innanför klassen?
Överväg följande kod från Tour of Heroes t.ex. på Angulars webbplats:
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero.service';
@Component({
moduleId: module.id,
selector: 'my-dashboard',
templateUrl: `dashboard.component.html`,
styleUrls: ['dashboard.component.css']
})
export class DashboardComponent implements OnInit {
heroes: Hero[] = [];
constructor(private heroService: HeroService) { }
ngOnInit(): void {
this.heroService.getHeroes()
.then(heroes => this.heroes = heroes.slice(1, 5));
}
}
Om jag deklarerar heroService utanför konstruktören som nedan, kastar appen många fel.
export class DashboardComponent implements OnInit {
heroes: Hero[] = [];
constructor() { }
private heroService: HeroService;
ngOnInit(): void {
this.heroService.getHeroes()
.then(heroes => this.heroes = heroes.slice(1, 5));
}
}
Såvitt jag förstår genererar det inte en instans av serviceklassen HeroService att skriva det utanför konstruktorn, men varför? (Är det en Angular-grej eller TypeScript?) I detta exempel är Hero också en klass (även om det inte är en serviceklass, men ändå tekniskt sett en klass!), och vi har deklarerat heroes: Hero[]=[]; utanför konstruktorn, och det fungerar.
Svar #1
Angular DI undersöker konstruktorns parametrar och när Angular DI skapar en ny instans av en klass (service, komponent, direktiv, pipe), letar det upp matchande leverantörer som ska skickas till konstruktorn.
Därför,
injektion fungerar endast för klasser instansierade av DI
endast konstruktörsparametrar beaktas för injektion
Svar #2
Det du har beskrivit här är en egenskaps(injector) injection som i teorin är möjlig men som generellt inte rekommenderas, även känd som en dålig praxis.
För att förstå detta lite bättre bör du läsa om konstruktörsinjektion och varför det föredras framför andra typer av injektioner som till exempel egenskapsinjektion.
Såvitt jag vet har Angular inte implementerat andra typer för att tvinga utvecklare att använda bästa praxis, därför kan du inte använda det utanför konstruktorn.
Angular 1 refererar till detta dokument som du kan läsa för att förstå det mer på djupet. Oroa dig inte för att det är från en tidigare version, det här är konceptuella termer som är irrelevanta för ramverket eller språket, så du kan läsa det för att förstå grunderna.
P.S. Glöm inte att om du har en variabel i konstruktorn på det sätt du har i Typescript (med private) kommer det automatiskt att skapa en egenskap. Så när du har den i en konstruktor injicerar Angular den där och Typescripts skapar implicit ett fält som i ditt sista kodexempel och initialiserar det från konstruktorns parameter.