2016-05-27 9 views
0

性能上の理由から、私は自分のコンポーネントに対して手動の変更の検出を設定しようとしています。Angular2の観測可能な変更検出テンプレートの更新

アプリの構造:アプリケーション - >ブック(S) - >ページ(複数可)

私はAppComponentで観測可能に加入するには、私はその後、ChangeDetectorRefの "markForCheck" メソッドを実行します。

これはBookComponent(更新用にマークしたコンポーネントの子)でngAfterContentCheckedメソッドをトリガーしているようです。

これは、親コンポーネントの "markForCheck"もすべての子を更新すると考えました。

ただし、ngAfterContentCheckedが子(BookComponent)で実行されても、このコンポーネントのテンプレートは更新されません!

私はすべての子供(時にはコンポーネント階層のいくつかの深いところ)で観察可能なものを聞くはずですか?それとも私は何か悪いことをしましたか?そして、テンプレートが更新されないのに、なぜngAfterContentCheckedが子コンポーネントで実行されるのですか?

関連するコードのいくつか。

@Component({ 
    selector: 'app', 
    directives: [BookComponent], 
    changeDetection: ChangeDetectionStrategy.OnPush, 
    template: ` 
     <book *ngIf="_book" [book]="_book" [style.height]="_availableDimensions.height+'px'" (window:resize)="onResize($event)"></book> 
     <footer id="footer"></footer> 
    ` 
}) 

export class PlayerComponent { 
    ngOnInit() { 
     this.initScale(); 
    } 

initScale(){ 
     this._playerService.availableDimensions$.subscribe(
      availableDimensions => { 
       // set local availableDimensions variable 
       this._availableDimensions = availableDimensions; 
       this._cd.markForCheck(); 
      } 
     ); 
    } 
} 



@Component({ 
    selector: 'book', 
    directives: [PageComponent], 
    changeDetection: ChangeDetectionStrategy.OnPush, 
    template: ` 
     <div id="pageScrollZone"> 
      <div id="pageHolder" [ngStyle]="pageHolderStyles()"></div> 
     </div> 
    ` 
}) 

export class BookComponent { 
    constructor(
      private _cd: ChangeDetectorRef, 
      private _playerService: PlayerService, 
      private _config: Config 
    ){} 

    ngAfterContentChecked(){ 
// This part does execute when the observable changes 
     let date = new Date(); 
     console.log('BOOK: '+date.getHours()+':'+date.getMinutes()+':'+date.getSeconds()); 
    } 

    pageHolderStyles(){ 
// This part does NOT execute when the observable changes 
     let styles = { 
      marginTop: this._currentMargin.y+'px', 
      transform: 'scale('+ (this._baseZoom * this._currentZoomLevel) +')' 
     } 

     return styles; 
    } 
} 
+2

言葉は安いです - 私たちにいくつかのコードを示す;-)理想的にpl unkerは再現を可能にする。 –

答えて

2

すっごく...二つの迅速な物事..

まず、あなたがmarkForCheck()を使用する場合、それは角度が変更を実行すべきかのパスをマークするコンポーネント自体ルートコンポーネント間行きますを検出する。

From a great Thoughtram Article: tree

「私たちは。markForCheck(と呼ばれるAPIが付属しています依存 注入、)を経由して私たちが必要とするまさにん このメソッドを、コンポーネントのChangeDetectorRefにアクセスすることができます!それは私たちからのパスをマークコンポーネントが ルートまで次回の変更検出の実行を確認する必要があります。

トリガーすると、それは自分の子供ではありませんが、それはルートコンポーネントに向かって見えます。子供たちもonPushであれば、更新は無視されます。

私は、すべての子供(時にはコンポーネント階層のいくつかの深さ)で観察可能なものを聞くはずですか?

すべての要素を明示的にonPushにしたい場合のみ。 私はあなたが欲しいですかが親であれば自動的に更新されます...あなたは運が良かったです!あなたがコンポーネントのページで標準戦略を使用して検出がツリーを下に実行したときにブックonPush戦略を使用する場合には、子どもたちが通常の部品であっても、そのブランチをスキップします。Source:Victor Savkin so noあなたは、ブレークしたい場所のどこにでも、深く耳を傾ける必要はありません。 onPushであるすべてのコンポーネントは、それを動作させる必要がある場合は、パフォーマンスの向上を保証しません。ほとんどの場合、重要なノードをブロックするだけで十分です。

2つ目はおよそngAfterContentChecked それは既知のバグですされています。だから、彼らはそれについて知っている

(全く同じ)https://github.com/angular/angular/issues/7055

(関連、両方に優れた議論)https://github.com/angular/angular/issues/7054

、それは実際に検出を実行していませんが、それはコールバックを発射しています...

関連する問題