ExpressionChangedAfterItHasBeenCheckedError - Expression has changed after it was checked

137 阅读1分钟

Expression has changed after it was checked

参考链接

一个能够完美重现该问题的例子:

export class BankAccount implements OnChanges{
  ngOnChanges(changes: SimpleChanges): void {
    /*console.log('ngOnChanges triggered: ' + changes.bankName.currentValue + ' previous value: ' + changes.bankName.previousValue);*/
  }
  // This property is bound using its original name.
  /*
  @Input()
  set bankName(newName) {
    console.log('bankName new value set: ' + newName);
  }*/

  @Input()
  bankName:string;

  // this property value is bound to a different property name
  // when this component is instantiated in a template.
  @Input('account-id') 
  
  id: string;

  // this property is not bound, and is not automatically updated by Angular
  normalizedBankName: string;
}

@Component({
  selector: 'app',
  template: `
    <bank-account [bankName]="bankName" account-id="4747"></bank-account>
  `
})
export class App implements OnInit, AfterViewInit{

  _bankName = 'Jerry';

  ngAfterViewInit(): void {
    this._bankName = 'Jerry2';
  }

  get bankName(){
    return this._bankName;
  }

  ngOnInit(): void {
  }

}

root cause

The problem here is that we have a situation where the view generation process (which ngAfterViewInit is a part of) is itself further modifying the data that we are trying to display in the first place:

在view构建过程中,试图修改一个我们原本打算显示在视图上的数据,导致了这个错误。

解决方法:

把赋值操作包裹到setTimeout里即可:


setTimeout能够工作的原因

Angular then finishes rendering the view and reflects the latest data changes on the screen, and the Javascript VM turn completes

更多Jerry的原创文章,尽在:“汪子熙”: