2016-05-27 53 views
0

出於性能方面的原因,我試圖在我的組件上設置手動更改檢測。Angular2可觀察的更改檢測模板更新

該應用的結構:應用程序 - >書(S) - >網頁(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允許重現的未知者。 –

回答

2

的sooo ...兩個快速的東西..

首先,當你使用markForCheck()是不言而喻的組件本身根組件之間,以紀念什麼角度應該運行變化的路徑檢測。

From a great Thoughtram Article: tree

「我們可以通過依賴 注入,其中附帶了一個名爲markForCheck()的API。該方法 不正是我們所需要的!它標誌着從路徑訪問組件的ChangeDetectorRef我們組件直到 根檢查下一次更改檢測運行。「

所以,當你觸發它不看它自己的孩子,它看起來朝着根組件。如果它的孩子也在onPush,他們會忽略它的更新。

我應該聽每個孩子的觀察值(有時在組件層次結構的幾個級別)?

只有當你想所有的元素明確onPush。 我的猜測是你想要頁面自動更新,如果它的父母沒有......那麼你很幸運!如果您使用組件的頁面標準戰略當檢測運行在樹中使用onPush戰略SKIP分支,即使孩子是正常的部件。Source:Victor Savkin

所以沒有你不必深深地傾聽觀察者,無論你想要休息的地方。 如果你不得不欺騙它進入工作狀態,那麼每個onPush組件都不能保證性能增益。在大多數情況下,僅阻塞關鍵節點就足夠了。

的第二件事是關於ngAfterContentChecked 這是一個已知的bug:

(完全相同)https://github.com/angular/angular/issues/7055

(相關,更好雙方討論)https://github.com/angular/angular/issues/7054

所以他們知道這一點,它實際上並沒有運行檢測,但它觸發回調...