Angular為什麼需要service
- 元件應該是專注於展示層,所以需要service來獲取資料和儲存資料。
- 元件之間的通訊需要service來協助完成。
眾所周知,angular中service採用的是依賴注入,那什麼是依賴注入呢?
為什麼需要依賴注入
從一個小例子說起
export class Car {
public engine: Engine; // 引擎
public tires: Tires; // 輪胎
constructor() {
this.engine = new Engine();
this.tires = new Tires();
}
}
//如果更換了引擎的建構函式,要傳入氣缸數,建構函式則要跟著改
constructor() {
this.engine = new Engine(12);
this.tires = new Tires();
}
複製程式碼
上面建立了一個汽車類,但是這個類完全沒有健壯性。假如引擎的建構函式改變了,構建引擎的時候需要傳一個引數,我們就得去汽車類裡面改變new Engine()這個使用。如果僅僅是需要改兩個地方可能還能接受,但是如果引擎類還依賴別的零件,這麼一層層的依賴關係,其中一個建構函式要發生改變了,可能會導致一連串的改變,會導致寫出來的程式碼完全沒有可維護性。輪胎也是如此,不同的汽車需要不同的輪胎,那麼像上述這麼寫就不太靈活,沒有通用性可言。
所以這樣就需要依賴注入
export class Car {
constructor(public engine: Engine, public tires: Tires) { }
}
let car = new Car(new Engine(), new Tires());
複製程式碼
這樣 engine和tire 和car類就是分離的,只要你是傳入的引擎和輪胎是滿足要求的,那麼這個car就是okay的。
class Engine2 {
constructor(public cylinders: number) { }
}
// 如果需要一個12缸的引擎, 這樣我們完全不用動car類。
let bigCylinders = 12;
let car = new Car(new Engine2(bigCylinders), new Tires());
複製程式碼
依賴注入這種模式也為編寫測試用例提供了方便,在測試car類的時候,你不必去關係輪胎細節,只要給出一個可用的輪胎就行。
上面解釋了依賴注入是什麼,以及為什麼需要依賴注入。就是一個類從外界接受他所需要的依賴關係,而不是自己去創造它們。但是對於消費者,問題又來了。想要一輛車,就必須得有一個工廠來組裝出一個車
import { Engine, Tires, Car } from './car';
export class CarFactory {
createCar() {
let car = new Car(this.createEngine(), this.createTires());
car.description = 'Factory';
return car;
}
createEngine() {
return new Engine();
}
createTires() {
return new Tires();
}
}
複製程式碼
這個模式看來起似乎沒有問題,但是這只是簡化的依賴,類似的引擎工廠類, 輪胎工廠類,相互呼叫,相互依賴,這會形成一個不可維護的?️
這個時候就需要一個依賴注入框架了。這個框架有一個叫注入器的東西,需要一個Car時, 只需要
let car = injector.get(Car);
複製程式碼
這樣消費者也不用去維護生產car的工廠類。並且car類本身也不管輪胎,引擎怎麼來的。皆大歡喜。
angular中依賴注入模式
angular中採用的是分層依賴注入
angular的應用程式是一個元件樹,每一個元件例項化都有自己的注入器providers。
元件在找service的時候會一直向上冒泡尋找,直到找到根元件AppComponent還沒有找到的時候就會報錯。
這樣設計的好處:
- 便於元件之間的通訊。頂層一點的元件可以統一控制多個子元件的對同一個資料的操作。
- 增加複用。可以抽出多個底層元件複用的service寫在上層元件中。
angular中service的小知識
- 生成一個module的service。 ng g service test --module=app
- 採用 @Injectable()裝飾器,這個東西告訴angular這個服務類可能本身注入了依賴,
- 元件本身是不管服務內部怎麼運作。
- service是必須通過providers注入。
- 是可以在服務的建構函式中呼叫一些業務函式 ,但不是最佳實踐。
- 服務在app內是單例的。
src/app/test.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class TestService {
constructor() { }
}
複製程式碼