Angular-添加动态组件时发生异常 [英] Angular - Exception when adding dynamic component

查看:49
本文介绍了Angular-添加动态组件时发生异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的测试代码,用于使用Angular 4添加动态组件.

I have a simple test code for adding dynamic components with Angular 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)
  }

}

所有这些代码所做的就是在末尾添加一个虚拟模板.

All this code is doing is adding a dummy template at the end.

但是此代码引发异常:

ExpressionChangedAfterItHasBeenCheckedError:表达式已更改经过检查后.上一个值:未定义".当前值: ''.似乎该视图是在其父级和孩子们已经脏了检查.是否已在更改中创建检测钩?

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 ?

这是描述性很好的例外.在检查更改后,视图已更新.

It is well descriptive exception. A view has been updated after already checked for changing.

但是我在这里有些不明白的地方:

But there are few things which I don't understand here :

问题:

1:

如果我从模板中删除了 input ,那么现在的模板是:

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

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

-那么我没有例外.为什么会这样?

— Then I don't get an exception. Why is that ?

2:

另一种解决方案是将 ngAfterViewInit 替换为 ngAfterContentInit .我已经知道两者之间的区别.

Another solution(among many) is to replace ngAfterViewInit with ngAfterContentInit. I already know the difference between those two.

如果是这样-我可以得出结论(发生异常的事实)在每个Angualr事件中-都发生了更改检测?(这很有意义,因为 ngAfterViewInit 发生_after_ ngAfterContentInit ),所以Angular可能已经检测到 ngAfterViewInit 中的上一个动态变化.?我说的对吗?

If so - can I conclude ( from the fact that the exception is gone) that at each Angualr's event - a change detection is occurred? (which make sense becuase ngAfterViewInit happens _after_ ngAfterContentInit) , so maybe Angular has detected the prev dynamic change in ngAfterViewInit ? Am I right?

PLNKR

推荐答案

如果我从模板中删除输入-现在模板是:

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

输入未引起问题. ngModel 指令会导致问题.指令和组件实例表示为angular内的视图节点-当前组件的子级.在每个变更检测周期内,Angular会更新这些组件/指令实例的输入.以下摘录自您需要了解的有关Angular变更检测的所有信息,其中显示了操作顺序:

The input is not causing the problem. ngModel directive causes a problem. Directives and components instances are represented as view nodes inside angular - sort of children of the current component. During each change detection cycle, Angular updates inputs for these component/directive instances. Here is the excerpt from the Everything you need to know about change detection in Angular that shows the order of operations:

  • 更新子组件/指令实例(1)上的 input 属性
  • 组件/指令实例上调用 AfterContentInit 和AfterContentChecked生命周期挂钩(5)
  • 运行子视图的更改检测(重复此列表中的步骤)(8)
  • 组件/指令实例上调用 AfterViewInit 和AfterViewChecked生命周期挂钩(9)
  • 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)

因此,假设Angular正在对AppComponent进行更改检测.它为 _Component (6)运行更改检测.尚无指令,因此无需检查.然后,Angular调用 _Component afterViewInit 钩子,在其中创建子指令实例 ngModel .但是,从未触发指令 ngModel 的更改检测!当前的更改检测周期结束后,Angular检查更改,并发现 ngModel @Input 是空字符串,但先前的值是 undefined ,因为它从未被检查过.

So assume that Angular is doing change detection for the AppComponent. It runs change detection for the _Component (6). There are no directives yet so nothing to check. Then Angular calls afterViewInit hook for the _Component, where you create a child directive instance ngModel. But the change detection for the directive ngModel is never triggered! After the current change detection cycle is finished, Angular checks for changes and finds that @Input of ngModel is an empty string, but the previous values is undefined since it was never checked.

与使用 AfterContentInit 挂钩的情况进行比较.挂接到 _Component 的角度调用.您在此处创建一个子指令.Angular运行 _Component 的更改检测.现在,该指令已经存在,因此也将对此子指令运行更改检测,作为 _Component 的更改检测的一部分.由于Angular应用了空字符串初始值,因此下次检查该指令时不会发生错误.

Compare that with the case when you used AfterContentInit hook. Angular calls that hook for _Component. You create a child directive there. Angular runs change detection for the _Component. Now, the directive already exists so change detection is also run for this child directive as part of change detection for the _Component. Since Angular applied empty string initial value, no error occurs next time the directive is checked.

这篇关于Angular-添加动态组件时发生异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆