อัพเดท 2016-06-27:แทนที่จะใช้ Observables ให้ใช้อย่างใดอย่างหนึ่ง
- a BehaviorSubject ตามคำแนะนำโดย @Abdulrahman ในความคิดเห็นหรือ
- ReplaySubject ตามที่แนะนำโดย @Jason Goemaat ในความคิดเห็น
เรื่องเป็นทั้งสังเกต (เพื่อให้เราสามารถsubscribe()
อยู่กับมัน) และสังเกตการณ์ (เพื่อให้เราสามารถเรียกnext()
มันจะออกมาเป็นค่าใหม่) เราใช้ประโยชน์จากคุณลักษณะนี้ หัวเรื่องให้ค่าเป็นมัลติคาสต์แก่ผู้สังเกตการณ์หลายคน เราไม่ใช้ประโยชน์จากคุณลักษณะนี้ (เรามีผู้สังเกตการณ์เพียงคนเดียวเท่านั้น)
BehaviorSubjectเป็นตัวแปรของหัวเรื่อง มันมีความคิดของ "มูลค่าปัจจุบัน" เราใช้ประโยชน์จากสิ่งนี้: ทุกครั้งที่เราสร้าง ObservingComponent มันจะได้รับค่ารายการการนำทางปัจจุบันจาก BehaviorSubject โดยอัตโนมัติ
รหัสด้านล่างและตัวเรียงลำดับใช้ BehaviorSubject
ReplaySubjectเป็นอีกหนึ่งตัวแปรของหัวเรื่อง หากคุณต้องการรอจนกว่าจะมีการสร้างค่าใช้งานReplaySubject(1)
จริง ในขณะที่ BehaviorSubject ต้องการค่าเริ่มต้น (ซึ่งจะมีให้ในทันที) ReplaySubject ไม่ ReplaySubject จะให้ค่าล่าสุดเสมอ แต่เนื่องจากไม่มีค่าเริ่มต้นที่ต้องการบริการจึงสามารถดำเนินการ async บางอย่างก่อนส่งคืนค่าแรก มันจะยังคงทำงานทันทีเมื่อมีการโทรตามมาด้วยค่าล่าสุด หากคุณต้องการเพียงหนึ่งค่าใช้first()
ในการสมัครสมาชิก 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
คำตอบเดิมที่ใช้ Observable: (ต้องใช้รหัสและตรรกะมากกว่าการใช้ BehaviorSubject ดังนั้นฉันไม่แนะนำ แต่อาจเป็นคำแนะนำ)
ดังนั้นนี่คือการดำเนินการที่ใช้สังเกตแทน EventEmitter ซึ่งแตกต่างจากการใช้งานของ EventEmitter ของฉันการใช้งานนี้ยังเก็บสิ่งที่เลือกไว้navItem
ในปัจจุบันเพื่อให้เมื่อองค์ประกอบการสังเกตถูกสร้างขึ้นมันสามารถดึงค่าปัจจุบันผ่านการเรียก API navItem()
และจากนั้นจะได้รับแจ้งการเปลี่ยนแปลงผ่านnavChange$
Observable
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
ดูเพิ่มเติมตัวอย่างตำราการโต้ตอบของส่วนประกอบซึ่งใช้Subject
เพิ่มเติมจากสิ่งที่สามารถสังเกตได้ แม้ว่าตัวอย่างคือ "การสื่อสารระหว่างผู้ปกครองและเด็ก ๆ " เทคนิคเดียวกันนี้สามารถใช้ได้กับส่วนประกอบที่ไม่เกี่ยวข้อง