在Angular2裡面如何做一個全域型的變數然後當其更新時,讓所有有用到的人都知道。這時候就要用EventEmitter了
EventEmitter是什麼? 官方文件裡尚未仔細描述他的用途,但是我覺得他有點類似Angular1的 $broadcast,以下是EventEmitter所提供的method
1 2 3 4 5 6
| class EventEmitter { constructor(isAsync?: boolean) emit(value: T) next(value: any) subscribe(generatorOrNext?: any, error?: any, complete?: any) : any }
|
如何用呢?
1 2 3 4 5 6 7 8 9
| open: EventEmitter<any> = new EventEmitter();
open.emit(<value>);
open.subscribe((value)=>{ .... })
|
當emit被呼叫時,subscribe就會接收到通知,然後就會進行subscribe第一個function的動作。
利用這個特性,可以在service裡面寫全域變數。程式碼如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import { Injectable, EventEmitter } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/Rx';
import { AngularFire, AuthMethods, FirebaseAuthState, AuthProviders } from 'angularfire2';
@Injectable() export class AuthService {
currentUser: FirebaseAuthState; checkLogin: EventEmitter<any> = new EventEmitter(); constructor(private af: AngularFire) { }
get isLogin(): boolean { ... } login(cred): Observable<FirebaseAuthState> { let ob = Observable.fromPromise(this.af.auth.login(cred, { provider: AuthProviders.Password, method: AuthMethods.Password, })); return ob.do((data) => { this.setUser(data); }) }
fbLogin() { ... } logout() { localStorage.removeItem('objUser'); this.currentUser = undefined; this.af.auth.logout(); this.checkLogin.emit(this.isLogin); }
private setUser(user) { localStorage.setItem('objUser', JSON.stringify(user)); this.currentUser = user; this.checkLogin.emit(this.isLogin); } }
|
但是,Provider Inject的位置要注意(請參考Angular 2 Components and Providers: Classes, Factories & Values),根據實驗,如果Component各自DI service as provider. 當其一的service值有改變而且有廣播時,另外一個service是收不到的,看起來應該是不同的Instance造成的現象,所以必須在往上一層注入服務.
參考文件