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

@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]

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


当前回答

ngAfterViewChecked()为我工作:

import { Component, ChangeDetectorRef } from '@angular/core'; //import ChangeDetectorRef

constructor(private cdr: ChangeDetectorRef) { }
ngAfterViewChecked(){
   //your code to update the model
   this.cdr.detectChanges();
}

其他回答

简单:首先在你的组件结构中分离/移除变更检测,然后在ngAfterViewInit()方法中启用detectChanges()

constructor(private cdr: ChangeDetectorRef) {
  this.cdr.detach() // detach/remove the change detection here in constructor
}


ngAfterViewInit(): void {
  // do load objects or other logics here
  
  // at the end of this method, call detectChanges() method.
  this.cdr.detectChanges(); // enable detectChanges here and you're done.
}

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

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

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

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

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

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

我认为最简单的解决方法如下:

Make one implementation of assigning a value to some variable i.e. via function or setter. Create a class variable (static working: boolean) in the class where this function exists and every time you call the function, simply make it true whichever you like. Within the function, if the value of working is true, then simply return right away without doing anything. else, perform the task you want. Make sure to change this variable to false once the task is completed i.e. at the end of the line of codes or within the subscribe method when you are done assigning values!

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

ngOnInit() {
    this.updateMessage();
}

在RC1中,这不会触发异常

我不能评论@Biranchi的帖子,因为我没有足够的声誉,但它为我解决了这个问题。

有一件事要注意! 如果添加changeDetection: ChangeDetectionStrategy。OnPush在组件上没有工作,它是一个子组件(哑组件)尝试添加到父组件也。

这修复了bug,但我想知道这有什么副作用。