2016-06-27 Güncellemesi: Gözlemlenebilirler kullanmak yerine aşağıdakilerden birini kullanın:
- @Abdulrahman tarafından bir yorumda önerildiği gibi bir BehaviorSubject veya
- @Jason Goemaat tarafından bir yorumda önerildiği gibi bir ReplaySubject
Bir Konu hem bir Gözlemlenebilir (bunu yapabiliriz subscribe()
) hem de bir Gözlemcidir (böylece next()
yeni bir değer yaymak için onu çağırabiliriz ). Bu özellikten yararlanıyoruz. Bir Konu, değerlerin birçok Gözlemci için çok noktaya yayın olmasına izin verir. Bu özellikten faydalanmıyoruz (sadece bir Gözlemcimiz var).
BehaviorSubject , Subject'nin bir varyantıdır. "Geçerli değer" kavramına sahiptir. Bundan yararlanıyoruz: Bir ObservingComponent oluşturduğumuzda, geçerli gezinme öğesi değerini BehaviorSubject öğesinden otomatik olarak alır.
Aşağıdaki kod ve dalgıç BehaviorSubject kullanır.
ReplaySubject , Subject'nin başka bir çeşididir. Bir değer üretilinceye kadar beklemek istiyorsanız, kullanın ReplaySubject(1)
. Bir BehaviorSubject bir başlangıç değeri gerektirdiğinden (hemen sağlanacaktır), ReplaySubject gerektirmez. ReplaySubject her zaman en son değeri sağlar, ancak gerekli başlangıç değerine sahip olmadığından, hizmet ilk değerini döndürmeden önce bazı zaman uyumsuz işlemler yapabilir. En son değere sahip sonraki aramalarda hemen tetiklenir. Sadece bir değer istiyorsanız first()
, aboneliği kullanın . Kullanırsanız abonelikten çıkmanız gerekmez first()
.
import {Injectable} from '@angular/core'
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Injectable()
export class NavService {
// Observable navItem source
private _navItemSource = new BehaviorSubject<number>(0);
// Observable navItem stream
navItem$ = this._navItemSource.asObservable();
// service command
changeNav(number) {
this._navItemSource.next(number);
}
}
import {Component} from '@angular/core';
import {NavService} from './nav.service';
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number;
subscription:Subscription;
constructor(private _navService:NavService) {}
ngOnInit() {
this.subscription = this._navService.navItem$
.subscribe(item => this.item = item)
}
ngOnDestroy() {
// prevent memory leak when component is destroyed
this.subscription.unsubscribe();
}
}
@Component({
selector: 'my-nav',
template:`
<div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
<div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>`
})
export class Navigation {
item = 1;
constructor(private _navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this._navService.changeNav(item);
}
}
Plunker
Gözlemlenebilir kullanan orijinal yanıt: (BehaviorSubject kullanmaktan daha fazla kod ve mantık gerektirir, bu yüzden tavsiye etmiyorum, ancak öğretici olabilir)
Yani, burada EventEmitter yerine Gözlemlenebilir kullanan bir uygulama . EventEmitter uygulamamın aksine, bu uygulama o anda seçili navItem
olan hizmeti de depolar , böylece bir gözlemleme bileşeni oluşturulduğunda, geçerli değeri API çağrısı yoluyla alabilir navItem()
ve ardından navChange$
Gözlemlenebilir aracılığıyla değişikliklerden haberdar edilebilir .
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/share';
import {Observer} from 'rxjs/Observer';
export class NavService {
private _navItem = 0;
navChange$: Observable<number>;
private _observer: Observer;
constructor() {
this.navChange$ = new Observable(observer =>
this._observer = observer).share();
// share() allows multiple subscribers
}
changeNav(number) {
this._navItem = number;
this._observer.next(number);
}
navItem() {
return this._navItem;
}
}
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number;
subscription: any;
constructor(private _navService:NavService) {}
ngOnInit() {
this.item = this._navService.navItem();
this.subscription = this._navService.navChange$.subscribe(
item => this.selectedNavItem(item));
}
selectedNavItem(item: number) {
this.item = item;
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
@Component({
selector: 'my-nav',
template:`
<div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
<div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
`,
})
export class Navigation {
item:number;
constructor(private _navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this._navService.changeNav(item);
}
}
Plunker
Ayrıca, gözlemlenebilirlere ek olarak kullanılan Bileşen Etkileşimi Yemek Kitabı örneğine bakın Subject
. Örnek "ebeveyn ve çocuk iletişimi" olmasına rağmen, aynı teknik ilişkisiz bileşenler için de geçerlidir.