2017-04-17 93 views
4

我遇到了一個簡單的問題,它有一個簡單的解決方案setTimeout(...,0)Angular 4 - 什麼是「等待手術」的正確方法?

望着這個簡單的代碼:

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <input value='Fill Data' type='button' (click)='fill()'/> 
     <span *ngFor="let o of Items" class='mySpan'>Span To Detect<br></span> 
    </div> 
    `, 
}) 
export class App { 
    Items:Array<number> = new Array<number>(); 

    fill() 
    { 
    this.Items = [1,2,3,4,5,6,7,8,9,10] 
    this.analyzeDom(); //this has to run here 
    } 

    analyzeDom() 
    { 
     alert($("div .mySpan").length) // "0" 

    //BUT if I set this hacky trick , it works 
    // setTimeout(function(){ alert($("div .mySpan").length)},0) // "10" 
    } 
} 

如果我按一下按鈕,警報顯示爲 「0」。我明白爲什麼會發生。這是因爲Angular沒有完成它的週期來實際填充ngFor

但是 - 使用setTimeout(..,0)做這個詭計對我來說似乎有點冒失,我寧願不相信它。

問:

什麼是正確的方式在角 「等待作業」? (這樣我會看到「10」)?

Plnkr

+0

通過使用[生命週期鉤(https://angular.io/docs/ts/latest/guide/ lifecycle-hooks.html) - 'ngOnInit'或者不同的'ngDoCheck'方法 – mhodges

+0

@mhodges但是點擊按鈕可以點擊這個按鈕,並且在這些鉤子已經發生之後可以點擊這個按鈕 –

+0

你想要的原因是什麼使其同步和延遲功能,直到DOM將被更新?是不是更好地從當前模型讀取長度,而不是像'alert(this.Items.length)'這樣的DOM? – Kuba

回答

10

1)您可以強制角致電cdRef.detectChanges

constructor(private cdRef: ChangeDetectorRef) {} 

analyzeDom(){ 
    this.cdRef.detectChanges(); 
    alert($("div .mySpan").length) 

Plunker

至於setTimeout更新DOM是宏任務,因此它在運行下一個週期的消化。 這意味着在調用setTimeout後,所有組件樹都將被檢查

cdRef.detectChanges不會調用appRef.tick()。它只執行變更檢測組件本身及其子項。

2),或者你可以等到Angulat已經通過訂閱更新DOM來zone.onMicrotaskEmpty

import 'rxjs/add/operator/first'; 

constructor(private zone: NgZone) {} 
... 
this.zone.onMicrotaskEmpty.first().subscribe(() => this.analyzeDom()); 

注:第一個運營商可能會導致內存泄漏。看看https://github.com/angular/material2/issues/6905

訂閱onMicrotaskEmpty不調用變更檢測週期

Plunker

+0

你能解釋如何不同'setTimeout(... 0)'是而不是你的解決方案? –

+1

@Royi setTimeout的工作原理是因爲它將您傳遞給它的函數碰撞到下一個評估週期。因此,在您的代碼中進行更改,然後Angular檢測到這些更改並相應地更改DOM。在通過代碼之後,執行超時函數。真的不是一個很糟糕的解決方案,只是它不是一個Angular解決方案,因此很難。上面列出的解決方案明確表示在dom更新後執行我的代碼。 – SethWhite

+0

@SethWhite謝謝澄清,但是,我正在尋找一篇關於'onMicrotaskEmpty'的好文章(用於學習目的) - 仍然沒有找到任何 –

相關問題