2017-05-29 28 views
2

當我有一個簡單的測試代碼,用於將動態部件與角4.角 - 異常增加動態成分

@Component({ 
    selector: 'component', 
    template: ` 

    <ul><li #item *ngFor="let number of list">{{number}}</li></ul> 

    <ng-template #anchor> </ng-template> 


    <ng-template #template> 
     <li><input type="text" [(ngModel)]="myInput"/></li> 
    </ng-template>` 
}) 
class _Component { 

    @ViewChild('template') 
    template: TemplateRef<any> 


    @ViewChild('anchor', { read: ViewContainerRef }) 
    anchor: TemplateRef<any> 


    @ViewChildren('item', { read: ViewContainerRef }) 
    items: QueryList<ViewContainerRef> 
    myInput=''; 
    list: number[] = [0, 1, 2, 3, 4] 

    ngAfterViewInit() { 
    this.anchor.createEmbeddedView(this.template) 
    } 

} 

所有這些代碼正在做的是將在端部具有虛設模板。

enter image description here

但這代碼引發異常:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: ''. It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook ?

這是很好的描述例外。已經檢查更改後,視圖已更新。

但是,有一些我不明白這裏幾件事情:

問題(S):

1:如果我從模板中刪除input

- 所以現在的模板是:

<ng-template #template> 
    <li></li> 
</ng-template> 

- 然後我不' t得到一個例外。這是爲什麼 ?

2:

另一種解決方案(其中許多)是ngAfterContentInit取代ngAfterViewInit。我已經知道這兩者之間的區別。

如果是這樣 - 我可以得出結論(,因爲例外情況已不復存在)在每個Angualr事件中發生變化檢測? (這是有道理的,因爲ngAfterViewInit發生_after_ ngAfterContentInit),所以也許Angular已經檢測到ngAfterViewInit的prev動態變化?我對嗎?

PLNKR

+0

你爲什麼要插入'

+0

@Maximus它並不重要(恕我直言)。 Angular將動態內容添加爲A SIBLING。所以它真的沒關係。 –

+0

我建議你閱讀[你需要知道的關於角度變化檢測的所有內容](https://hackernoon.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f)以及[this](https://hackernoon.com/angulars-digest-is-reborn-in-the-newer-version-of-angular-718a961ebd3e#d14a) –

回答

3

If I remove the input from the template - so now the template is :

輸入不是造成問題的原因。 ngModel指令導致問題。指令和組件實例被表示爲當前組件的角度排序子視圖內的視圖節點。在每個更改檢測週期內,Angular更新這些組件/指令實例的輸入。下面是從Everything you need to know about change detection in Angular,顯示操作順序摘錄:

  • updates input properties on a child component/directive instances (1)
  • calls AfterContentInit and AfterContentChecked lifecycle hooks on child component/directive instances (5)
  • runs change detection for a child view (repeats the steps in this list) (8)
  • calls AfterViewInit and AfterViewChecked lifecycle hooks on child component/directive instances (9)

所以假設角做變化檢測爲AppComponent。它運行_Component(6)的變更檢測。沒有任何指令,所以沒有檢查。然後Angular調用afterViewInit鉤子_Component,在那裏你創建一個子指令實例ngModel。但是指令ngModel的更改檢測從未觸發!當前更改檢測週期結束後,Angular檢查更改並發現ngModel@Input是空字符串,但以前的值爲undefined,因爲它從未被檢查過。

與您使用AfterContentInit掛鉤的情況相比。支持_Component的角度調用。你在那裏創建一個子指令。角行程改變了對_Component的檢測。現在,該指令已經存在,所以更改檢測也針對此子指令運行,作爲_Component變更檢測的一部分。由於Angular應用了空字符串初始值,因此下次檢查該指令時不會發生錯誤。

+0

Maximus - 感謝您的文章。所以Angular在每個事件方法中都不會觸發變化檢測 - 僅在階段3,7,8? (換句話說 - 在什麼角度事件中 - 發生變化檢測?) –

+0

您可能必須閱讀整篇文章。本文中列出的所有操作都是特定視圖/組件的變化檢測的一部分。當你說'變化檢測'時,你可能會有不同的想法,'變化檢測'是什麼意思? –

+0

忘記它:-)。我將不得不閱讀它,如果我有問題 - 我會ping。 (順便說一句 - 我確實提到過,我知道事件的順序差異 - 在我的問題中,我不知道的是在每次事件中角度觸發器是否「改變檢測」 –