为什么这个组件在这个简单的砰砰声中

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App {
  message:string = 'loading :(';

  ngAfterViewInit() {
    this.updateMessage();
  }

  updateMessage(){
    this.message = 'all done loading :)'
  }
}

扔:

例外:表达式'I'm {{message}} in App@0:5'在被检查后发生了变化。之前的值:'I'm loading:('。当前值:'I'm all done loading:)' in [I'm {{message}} in App@0:5]

当我所做的一切都是更新一个简单的绑定时,我的视图被启动?


当前回答

它抛出一个错误,因为你的代码在ngAfterViewInit()被调用时被更新了。意思是当ngAfterViewInit发生时你的初始值被改变了,如果你在ngAfterContentInit()中调用它,那么它不会抛出一个错误。

ngAfterContentInit() {
    this.updateMessage();
}

其他回答

关于ExpressionChangedAfterItHasBeenCheckedError错误的一切你需要知道的文章详细解释了这种行为。

你设置的问题是ngAfterViewInit生命周期钩子是在变更检测处理DOM更新后执行的。你在这个钩子中有效地改变了模板中使用的属性,这意味着DOM需要重新渲染:

  ngAfterViewInit() {
    this.message = 'all done loading :)'; // needs to be rendered the DOM
  }

这将需要另一个变更检测周期,而Angular在设计上只运行一个摘要周期。

你基本上有两种解决方法:

使用setTimeout, Promise异步更新属性。然后在模板中引用异步可观察对象 在DOM更新之前执行钩子中的属性更新- ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked。

你也可以把你对updateMessage()的调用放在ngOnInt()-方法中,至少它对我有用

ngOnInit() {
    this.updateMessage();
}

在RC1中,这不会触发异常

我有同样的错误,我可以通过使用AfterViewInit和ChangeDetectionStrategy来解决它。OnPush

这是一篇详细的文章。 https://medium.com/@bencabanes/angular-change-detection-strategy-an-introduction-819aaa7204e7

正如drewmoore所说,在这种情况下,正确的解决方案是手动触发当前组件的变更检测。这是使用ChangeDetectorRef对象(从angular2/core导入)的detectChanges()方法完成的,或者它的markForCheck()方法,该方法也会更新任何父组件。相关例子:

import { Component, ChangeDetectorRef, AfterViewInit } from 'angular2/core'

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App implements AfterViewInit {
  message: string = 'loading :(';

  constructor(private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.message = 'all done loading :)'
    this.cdr.detectChanges();
  }

}

这里还有Plunkers演示了ngOnInit, setTimeout和enableProdMode方法以防万一。

在使用数据表时,我得到了类似的错误。当你在另一个*ngFor数据表中使用*ngFor时,会在它拦截角度变化周期时抛出这个错误。因此,不要在数据表内部使用数据表,而是使用一个常规的表或替换mf。带有数组名的数据。这很好。