可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'd like to watch an object/array, which ca be edited by a service or by a controllers routine. I thought that an Observable could watch an object/array.
My implementation doesn't react on changes of the items :
private data : Observable>; private dataObserver: Observer>; private sub : Subscription; private items: >; ngOnInit() { this.items = itemService.getItems(); this.data = new Observable>(observer =>{ this.dataObserver = observer; }); this.data.subscribe( x => console.log('onNext: %s', x), e => console.log('onError: %s', e), () => console.log('onCompleted') ); this.dataObserver.next(this.items); } private start(){ //change values of the array in an interval let loop = Observable.interval(250) let i=0; self.sub = loop.subscribe(() => { if(self.items[0]){ self.items[0].id= i; if(i
The observalbes subsciption doesn't react on changes of the items array. It only triggers on its next mehtod. On the other hand .. this is too cumbersome for a simple watch method.
What does angular-2 offer us to watch for changes, as $scope.$watch did in angular-1?
回答1:
Angular2 provides IterableDiffer
(array) and KeyValueDiffer
(object) to get information about differences between two checks.
NgClass
is a good example https://github.com/angular/angular/blob/14ee75924b6ae770115f7f260d720efa8bfb576a/modules/%40angular/common/src/directives/ng_class.ts#L122
See also https://angular.io/docs/ts/latest/api/#!?query=differ
An example
// inject a differ implementation constructor(differs: KeyValueDiffers) { // store the initial value to compare with this.differ = differs.find({}).create(null); } @Input() data: any; ngDoCheck() { var changes = this.differ.diff(this.data); // check for changes if (changes && this.initialized) { // do something if changes were found } }
回答2:
In the import section:
import { DoCheck, KeyValueDiffers, KeyValueChangeRecord } from '@angular/core';
Adding the 'KeyValueDiffers' injector:
private _differ: any; constructor(private _differs: KeyValueDiffers) { this._differ = _differs.find({}).create(); }
Finally track changes:
ngDoCheck() { const change = this._differ.diff(this.Your_Object_To_Track); if (change) { change.forEachChangedItem( (record: KeyValueChangeRecord) => { console.log(record.key + ': ' + record.previousValue + '=>' + record.currentValue) }); change.forEachRemovedItem( (record: KeyValueChangeRecord) => { console.log(record.key + ': ' + record.previousValue + '=>' + record.currentValue) }); change.forEachAddedItem((record: KeyValueChangeRecord) => { console.log(record.key + ': ' + record.previousValue + '=>' + record.currentValue) }); } }
回答3:
Thanks for your example Gunter.
I choose a quick solution based on your response.
I replace the OnInit handle by a DoCheck implementation. Now if value change in my service external called Language the view is updated.
In my case example :
import { Component, DoCheck } from "@angular/core"; export class LangListUserComponent implements DoCheck { constructor(private _languageService: LanguageService) {} ngDoCheck() { /** Get available lang */ this.oLanguages = this._languageService.getLanguageList(); this.setCurrentLang(this.oLanguages); }; }