angular2中應用obserable模式
在前面的學習中瞭解了angular2中元件的資料流,在元件間我們可以利用input、output實現元件間的資料傳遞。再來回顧一下前面的應用場景,一輛車(car)包含了引擎(engine)、門(door)等,車是父元件,門和引擎作為子元件。我們可以在引擎中加入一個啟動狀態(engineStatus),當引擎啟動時我們需要告知車,那麼我們需要在engine元件中output一個事件(EngineStatusChanged),並在engineStatus狀態改變時釋出event,而父元件car需要在訂閱這個引擎的事件[EngineStatusChanged]=”onEngineStatusChanged($event)”,通過$event引數我們在car元件中得到了engine的engineStatus,實現了子元件向父元件的資料傳遞,接下來如果車門(door)要通過了解引擎狀態來改變車門的狀態該如何處理呢?當然需要在door中加入一個input屬性用來接收car元件的繫結,實現父元件向子元件的資料傳遞。
從這個應用場景看,engine中的engineStatus是其一個屬性,它可以由它的使用者car讀取或更改,而無法讓與它無關的door直接進行訪問,這以為著這個值的變化是以樹狀結構進行擴散,那麼如果在這個樹上的一個節點訪問另一個節點的一個屬性將會導致在這兩個節點間的所有節點(根節點除外)都將要output、input這個屬性。如果我們的元件設計的扁平化,那麼這個問題到不大,但如果元件樹有一定深度後,這個效率就明顯不足了。
再仔細分析這個應用不難發現這是一個典型的觀察者模式應用,在angular2 中我們可以利用服務來實現這個模式,我們可以建一個服務,在服務中建立的一個觀察物件engineStatus,同時提供一個介面可以實現對更改這個物件的狀態,並將變化推送出去,觀察者訂閱這個觀察物件。檢視示例:
Car.service.ts
/**
* Created by Administrator on2016-06-16.
*/
import {Injectable}
from "@angular/core";
import {Observable, Observer}
from "rxjs/Rx";
@Injectable()
export class CarService{
engineStatus:Observable<boolean>;
private observer:Observer<boolean>;
constructor(){
this
}
changeEngineStatus(newstatus:boolean){
if(this.observer!==undefined)
this.observer.next(newstatus);
}
}
在這個服務中engineStatus是觀察物件,我們同時定義了一個observer用於推送狀態。changeEngineStatus方法是該服務對外公佈的一個用於改變觀察物件的一個方法,通過this.observer.next(newstatus)推送一個新的狀態。
Engine.ts
/**
* Created by Administrator on2016-06-16.
*/
import {Component}
from "@angular/core";
import {CarService} from"./car.service";
@Component({
selector:'engine',
template:`
<div style="background: rebeccapurple">
<p>this is engine</p>
<button (click)="onFired()">fire</button>
<button (click)="onUnFired()">unFire</button>
</div>
`
})
export class engine
{
constructor(private
carService:CarService){
}
onFired()
{
this.carService.changeEngineStatus(true);
}
onUnFired()
{
this.carService.changeEngineStatus(false);
}
}
通過注入服務,由事件去呼叫服務中公佈的方法去改變觀察物件的狀態。
Door.ts
/**
* Created by Administrator on2016-06-16.
*/
import {Component}
from "@angular/core";
import {CarService} from"./car.service";
@Component({
selector:'door',
template:`
<div style="background: gray">
<p>this is door</p>
<p *ngIf="engineStatus" >engine fired</p>
</div>
`
})
export class door{
engineStatus:boolean
= false;
subscription:any;
constructor(private
carService:CarService){
}
ngOnInit(){
this.subscription=this.carService.engineStatus.subscribe(status=>{this.engineStatus=status;});
}
ngOnDestroy(){
this.subscription.unsubscribe();
}
}
ngOnInit即是元件載入時實現對服務中engineStatus的訂閱 ,這樣只要服務推送一個值,那麼我們就可以通過這個訂閱 來實現獲取服務推送過來的值。
在這個例子中carService作為被觀察者,提供了一個觀察物件,同時提供了用於更新物件的介面,外部使用者只需訂閱這個觀察物件就可以獲取物件的值。同時我們會發現在這個示例中由於外部使用者相互間並不知道彼此的存在,這樣也會造成被觀察物件能夠被任意的更新,使用者也不知道是誰引發的改變,可能會導致一些邏輯上的混亂,在實際應用開發中就需要注意加入一些邏輯上的判斷。
通過這種方式,能夠在元件間很容易實現資料的傳遞,這種模式在angular2 內部就有大量的應用,其中最典型的就是http服務,這種模式更容易進行系統設計並且便於維護擴充套件。