詳解Angular依賴注入
概述
依賴注入:設計模式
依賴:程式裡需要的某種型別的物件。
依賴注入框架:工程化的框架
注入器Injector:用它的API建立依賴的例項
Provider:怎樣建立?(建構函式,工程函式)
Object:元件,模組需要的依賴
依賴性注入進階=>Angular中依賴注入框架提供父子層次注入型依賴
一、依賴注入
class Id { static getInstance(type: string): Id { return new Id(); } } class Address { constructor(provice,city,district,street) {} } class Person { id: Id; address: Address; constructor() { this.id = Id.getInstance("idcard"); this.address = new Address("北京","背景","朝陽區","xx街道"); } }
問題:Person需要清楚的知道Address和Id的實現細節。
ID和Address重構後,Pershttp://www.cppcns.comon需要知道怎麼重構。
專案規模擴大後,整合容易出問題。
class Id { static getInstance(type: string): Id { return new Id(); } } class Address { constructor(provice,street) {} } class Person { id: Id; address: Address; constructor(id: Id,address: Address) { this.id = id; this.address = address; } } main(){ WOGXlO//把構造依賴物件,推到上一級,推呼叫的地方 const id = Id.getInstance("idcard"); const address = new Address("北京","xx街道"); const person = new Person(id,address); }
Person已經不知道Id和Address的細節了。
這是最簡單的依賴注入。
問題是在main裡還是需要知道細節。
思路:一級一級往上推,一直推到入口函式,入口函式來處理所有物件的構造。構造出來後提供給所有依賴的子模組的子類。
問題:入口函式很難維護。所以需要一個依賴注入框架幫助完成。
二、Angular的依賴注入框架
從v5開始,因為速度慢,引入大量程式碼已棄用,改為Injector.create。
ReflectiveInjector :用於例項化物件和解析依賴關係。import { Component,ReflectiveInjector } from "@angular/core";resolveAndCreate接收一個provider陣列,provider告訴injector應該怎樣去構造這個物件。
constructor() { //接收一個provider陣列 const injector = ReflectiveInjector.resolveAndCreate([ { provide: Person,useClass:Person },{ provide: Address,useFactory: ()=>{ if(environment.production){ return new Address("北京","xx街道xx號"); }else{ return new Address("西藏","拉薩","xx區","xx街道xx號"); } } },{ provide: Id,useFactory:()=>{ return Id.getInstance('idcard'); } } ]); }
Injector:
injector相當於main函式,可以拿到所有依賴池子裡的東西。
import { Component,ReflectiveInjector,Inject} from "@angular/core"; import { OverlayContainer } from "@angular/cdk/overlay"; import { Identifiers } from "@angular/compiler"; import { stagger } from "@angular/animations"; import { environment } from 'src/environments/environment'; @Component({ selector: "app-root",templateUrl: "./app.component.html",styleUrls: ["./app.component.scss"] }) export class AppComponent { www.cppcns.com constructor(private oc: OverlayContainer) { //接收一個provider陣列 const injector = ReflectiveInjector.resolveAndCreate([ { provide: Person,useFactory:()=>{ return Id.getInstance('idcard'); } } ]); const person = injector.get(Person); console.log(jsON.stringify(person)); } } class Id { static getInstance(type: string): Id { return new Id(); } } class Address { provice:string; city:string; district:string; street:string; constructor(provice,street) { this.provice=provice; this.city=city; this.district=district; this.street=street; } } class Person { id: Id; address: Address; constructor(@Inject(Id) id,@Inject(Address )address) { this.id = id; this.address = address; } }
可以看到控制檯打印出person資訊。
簡寫:
// { // provide: Person,useClass:Person // },Person,//簡寫為Person
在Angular框架中,框架做了很多事,在provider陣列中註冊的東西會自動註冊到池子中。
@NgModule({ imports: [HttpClientModule,SharedModule,AppRoutingModule,BrowserAnimationsModule],declarations: [components],exports: [components,providers:[ {provide:'BASE_CONFIG',useValue:'http://localhost:3000'} ] })
constructor( @Inject('BASE_CONFIG') config) { console.log(config); //控制檯打印出http://localhost:3000 }
Angular預設都是單例,如果想要每次注入都是一個新的例項。有兩種方法。
一,return的時候return一個方法而不是物件。
{ provide: Address,useFactory: ()=>{ return ()=>{ if(environment.production){ return new Address("北京","xx街道xx號"); }else{ return new Address("西藏","xx街道xx號"); } } } },
二、利用父子Injector。
constructor(private oc: OverlayContainer) { //接收一個provider陣列 c程式設計客棧onst injector = ReflectiveInjector.resolveAndCreate([ Person,useFactory:()=>{ return Id.getInstance('idcard'); } } ]); const childInjector = injector.resolveAndCreateChild([Person]); const person = injector.get(Person); cowww.cppcns.comnsole.log(JSON.stringify(person)); const personFromChild = childInjector.get(Person); console.log(person===personFromChild); //false }
子注入器當中沒有找到依賴的時候會去父注入器中找
以上就是詳解Angular依賴注入的詳細內容,更多關於Angular的資料請關注我們其它相關文章!