3

私はobservableを使用してサービスからコンポーネントにコンポーネントを返し、ChangeDetectionStrategy.OnPushを使用しています。テンプレートでは、非同期パイプを使用しています変更検出は常に実行されるのではなく、新しいコンテンツが利用可能になった場合にのみ、パフォーマンス上の利点があります。以下は角度2 ChangeDetectionStrategy.OnPushと非同期パイプで観察可能

私のサービスである:私は私のコンポーネントで

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); 
    } 
} 

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(); 
    } 
} 

問題loadList内容は、HTTP呼び出してリストの内容をフェッチする場合ならば、ビューが更新され、リストの内容が静的である場合、ビューは更新されません。

私はsetTimeoutを内部リストの更新をラップした場合、それがトリガービューの更新私はちょうど観測を模索し始めた

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

は、誰もがいただきました!間違って上記のコードで案内してくださいすることができませんか?

答えて

2

コードフロンngOnInit()をコンストラクタに移動するだけです。 thod._list$nullであるため、角度が、ngOnInit()が呼び出されて失敗する前に、バインディングを解決しようとしました(監視対象に登録する)。変更を認識しないため、後で試行しません。

+0

Günterさん、ありがとうございました。しかし、これは問題を解決するようではありません。サービス内のloadListメソッドがhttp呼び出しを行う場合、またはsetTimeout(()=> { this._list $ .next(this.list); }、1);それ以外の場合は動作しません。 –

+0

'setTimeout()'は変更検出を実行させます。実際にコードをコンストラクタに移動しようとしましたか?最初の行をコンストラクタに移動するだけでよいでしょう。 –

+0

はい、私は行をthis.list $ = this._ls.list $;コンストラクタに渡します。 –