3

Ich benutze eine Observable, um eine Liste von Service zu meiner Komponente und in meiner Komponente Ich benutze ChangeDetectionStrategy.OnPush und in Vorlage Ich benutze asynchrone Rohr, in der Hoffnung Dies würde einen gewissen Leistungsvorteil bringen, da die Änderungserkennung nicht immer durchgeführt wird, sondern nur, wenn neue Inhalte verfügbar sind.Angular 2 Observable mit ChangeDetectionStrategy.OnPush und async pipe funktionieren nicht

Unten ist mein Service:

import { Injectable, Inject, EventEmitter } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import { Subject } from 'rxjs/Subject'; 

@Injectable() 
export class ListService { 

    public _list$: Subject<any[]>; 

    private list: any[] = []; 

    constructor() { 
     this._list$ = <Subject<any>>new Subject(); 
    } 

    get list$() { 
     return this._list$.asObservable(); 
    } 

    loadList() { 
     //if this.list is populated through an http call the view is updated, 
     //if its a static list like below, it doesn't trigger view update. 
     //this.list = ['Red', 'Green', 'Yellow', 'Blue']; 
     this._list$.next(this.list); 
    } 
} 

In meiner Komponente habe ich:

import { Component, ChangeDetectionStrategy } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 

@Component({ 
    templateUrl: ` 
<ul> 
     <li *ngFor="let item of (list$ | async);"> 
      {{item}} 
     </li> 
    </ul> 
`, 
    changeDetection: ChangeDetectionStrategy.OnPush 
}) 
export class ListComponent { 

    public list$: Observable<any[]>; 

    constructor(
     private _ls: ListService 
    ) {} 

    ngOnInit() { 
     this.list$ = this._ls.list$; 
     this._ls.loadList(); 
    } 
} 

Die Frage, ob die Ladeliste Inhaltsliste Inhalte über einen HTTP-Aufruf holen, wird die Ansicht aktualisiert, wenn die Listeninhalte sind statisch, die Ansicht wird nicht aktualisiert.

Wenn ich Liste Update innerhalb SetTimeout wickeln, es macht Ansicht Auslöser Update

setTimeout(() => { 
    this._list$.next(this.list); 
}, 1); 

Ich habe gerade angefangen Observable zu erkunden, kann mir jemand bitte führen, was ist falsch mit obigen Code?

Antwort

2

Verschieben Sie einfach den Code von ngOnInit() zum Konstruktor. Angular versucht, die Bindung aufzulösen (abonnieren Sie die Observable), bevor ngOnInit() aufgerufen wird und schlägt fehl, weil thod._list$null ist und nicht später versucht, weil es die Änderung nicht erkennt.

+0

Vielen Dank Günter für Ihre Antwort. Aber das scheint das Problem nicht zu lösen. Wenn die loadList-Methode im Dienst einen http-Aufruf ausführt oder wenn sie unter setTimeout (() => { this._list $ .next (this.list); } umbrochen wird, 1); es funktioniert, sonst nicht. –

+0

'setTimeout()' bewirkt, dass die Änderungserkennung ausgeführt wird. Haben Sie tatsächlich versucht, den Code in den Konstruktor zu verschieben? Sie könnten versuchen, die erste Zeile in den Konstruktor zu verschieben. –

+0

Ja, ich habe die Zeile this.list verschoben. $ = This._ls.list $; zum Konstruktor. –

Verwandte Themen