typescript - Hvordan utføre skitten-sjekk av itererbar komponentegenskap i Angular2?
Ta en titt på denne enkle Angular2-komponenten:
@Component({
selector: 'status-area',
directives: [],
template: require('./status-area.tpl.jade')
})
export class StatusAreaComponent {
constructor(private _settings: SettingsProvider) {}
get items() {
return _.filter(this._settings.features, (feature: any) => {
return feature.inStatusBar && feature.isEnabled;
});
}
}
SettingsProvider har en egenskap features, som blir endret av en annen komponent (for eksempel SettingsPanel). Denne komponenten er kun koblet via tjeneste (ingen inputparametere).
Så, som du har sett, trenger jeg å hente kun funksjoner som er aktivert og merket som status-linje-kompatible fra _settings.features-egenskapen.
For dette formålet bruker jeg lodash-metoden find.
Men som du kanskje antar, kaster Angular en unntakstilstand i utviklingsmodus:
Uttrykket har endret seg etter at det ble sjekket
Det skjer fordi _.filter() for hver gjennomgang returnerer en ny instans av array, men samlingen er den samme.
Mitt spørsmål er, hvordan løser du denne situasjonen? Eller kanskje det finnes en annen løsning/tilnærming for å håndtere denne saken.
Etter min mening ville det være veldig nyttig om Angular2 hadde en spesiell dekoratør som dette:
@checkIterable()
get items() {
return _.filter(this._settings.features, (feature: any) => {
return feature.inStatusBar && feature.isEnabled;
});
}
Selvfølgelig kan jeg løse dette ved å bruke en annen tilnærming, med hendelser og hendelseslytttere, men det produserte mye standardkode.
Se på dette eksempelet:
export class StatusAreaComponent implements OnInit, OnDestroy {
protected _items;
protected _removeWatcherFn;
constructor(private settings: SettingsProvider) {}
ngOnInit() {
this._items = this._fetchItems();
this._removeWatcherFn = this.settings.onChange.bind(() => {
this._items = this._fetchItems();
});
}
ngOnDestroy() {
this._removeWatcherFn();
}
_fetchItems() {
return _.filter(this.settings.features, (feature: any) => {
return feature.inStatusBar;
});
}
get items() {
return this._items;
}
}
På denne måten er Angular glad, men det er ikke jeg.
Svar #1
Siden du allerede bruker lodash, kan du bruke den praktiske _.memoize-metoden for å cache resultatet av filtrering. Den brukes vanligvis for å unngå kostbare beregninger, men i ditt tilfelle kan du dra nytte av dens bivirkning fordi Angular ikke vil ha dette problemet med at filtrerte arrays er forskjellige objekter for hver sjekk.
Her er en mulig løsning på problemet:
@Component({
selector: 'status-area',
directives: [],
template: require('./status-area.tpl.jade')
})
export class StatusAreaComponent {
constructor(private _settings: SettingsProvider) {
this.initFilter();
}
initFilter() {
function filterItems(items) {
return _.filter(items, (feature: any) => {
return feature.inStatusBar && feature.isEnabled;
})
}
this.filterFeatures = _.memoize(filterItems, function(items) {
return filterItems(items).map(item => item.id).join();
});
}
get items() {
return this.filterFeatures(this._settings.features);
}
}
Demo: http://plnkr.co/edit/MuYUO3neJdTs0DHluu0S?p=info
Svar #2
Du kan prøve klassen 'ChangeDetectorRef' og metoden 'detectChanges'.
Kanskje dette spørsmålet kan hjelpe deg:
- Uttrykk ___ har endret seg etter at det ble sjekket
