2017-02-10 55 views
-1

我有以下代碼...爲什麼我的Angular 2 * ngIf不能渲染直到函數完成?

// Pug Template 
.notification-header-area.layout-row.layout-align-center-center(*ngIf="notification.message != null", class="{{notification.color}}") 

// Inside angular component 
private onNotificationStart = (notification) => { 
     this.notification = notification; 
     console.log(this.myElement.nativeElement); 
     if (this.myElement.nativeElement.children.length > 0) { 
      // TODO: We should probably do this in a more reliable way in case the template changes. 
      let elm = this.myElement.nativeElement.children[0]; 
      if (notification.fontSize) elm.style.fontSize = notification.fontSize; 
      if (notification.colorBackground) elm.style.backgroundColor = notification.colorBackground; 
      if (notification.colorFont) elm.style.color = notification.colorFont; 
     } 
} 

的問題是,如果我在控制檯上線調試,瀏覽器不顯示通知DOM元素。 console.log語句在寫出對象時也會丟失它。如果函數完成運行ngIf呈現自己,我看到預期的元素。是否有$超時等值或什麼?我從Web套接字獲取此事件,並嘗試Trouble with *ngIf in Angular 2 (TypeScript),但它沒有奏效。我也無法在我簡單的插件(不使用網絡套接字)中重新創建它,所以我仍在研究演示。

另外,如果我換在這樣它的工作原理超時...

private onNotificationStart = (notification) => { 
    this.notification = notification; 
    setTimeout(() => { 
     console.log(this.myElement.nativeElement); 
     if (this.myElement.nativeElement.children.length > 0) { 
      // TODO: We should probably do this in a more reliable way in case the template changes. 
      let elm = this.myElement.nativeElement.children[0]; 
      if (notification.fontSize) elm.style.fontSize = notification.fontSize; 
      if (notification.colorBackground) elm.style.backgroundColor = notification.colorBackground; 
      if (notification.colorFont) elm.style.color = notification.colorFont; 
     } 
    }) 
    // if(notification){ 
    //  this.myElement.nativeElement.style.backgroundColor = 
    // } 
} 
+0

我不明白問題所在。預期的行爲是什麼? –

+1

爲什麼「* ngIf不能渲染直到函數完成」有問題? –

+0

這不具有相同的問題https://plnkr.co/edit/E2o56qn4el7cniofwvZK?p=preview所以我的不同是什麼? – Jackie

回答

1

簡短的回答:一切正常在這兩種情況下。如果你的期望不同,那就錯了。

的時間長一點......

你不能指望角度做一些魔術或比執行它的瀏覽器更聰明。 :)如果我們簡化一點... Javascript總是隻有一個執行線程(不考慮web工作者)。當你在你的函數中改變通知標誌時,在你的函數完成之前,外界不會發生任何事情,因爲它阻塞了唯一可用的執行線程。只有在此之後,稍後的某個時間點,更改檢測纔會啓動,並執行所有視圖同步,組件創建或銷燬以及其他所有必須完成的操作。這就是爲什麼它可以與setTimeout()一起工作 - 它爲所有這些事情發生提供了機會。

+0

爲什麼這不會有相同的問題呢,它應該是相似的,但這更多是我所期望的。 https://plnkr.co/edit/E2o56qn4el7cniofwvZK?p=preview – Jackie

+0

一切正常,因爲它應該在這個片段以及。你似乎對你的期望有點困惑。 –

1

Angular2(和4)使用zone.js修補異步API,如addEventHandlersetTimeout,....每當一個事件或setTimeout或另一異步API調用發生,角運行變化檢測的處理程序方法已經完成之後。更改檢測會導致更新視圖(綁定)。這也是當*ngIf得到更新。因此*ngIf在綁定變量被更新的方法結束後被更新,這正是預期的行爲。

更新

回調可能是跑到外面Angulars區,因爲網絡套接字API可能無法通過zone.js覆蓋。 您可以注入private zone:NgZone,敷代碼

this.zone.run(() => wrapped code here) 

或注入private cdRef:ChangeDetectorRef,並呼籲

this.cdRef.detectChanges(); 

綁定字段進行了更新,以顯式調用變化檢測之後。

+0

如果我記得我的web套接字實驗正確,它們被zone.js覆蓋,所以沒有必要將它包裝到這樣的東西中。重點在於OP將不得不使用setTimeout()。即使他在zone.run()內部運行了某些東西,也無濟於事,因爲角將繼續等待ngZone中所有任務的完成,並且只有在此之後,它纔會開始更改檢測以及所有這些內容。 –