在两个子组件之间传递变量会产生ExpressionChangedAfterItHaHasBeenCheckedError错误

时间:2019-02-25 11:32:02

标签: angular typescript

我有2个必须传递信息的子组件。

parent.component.html

<childA [loading]="loading">
    <childB (loadingChanged)="loadingChangedHandler($event)"></childB>
</childA>

parent.component.ts

loading = false;
constructor(){
   ......
}
loadingChangedHandler(loadingChild: boolean){
    this.loading = loadingChild;
  }

childB.component.ts(将变量传递给父级,该值传递给子级A)

....
@Output() loadingChanged: EventEmitter<boolean> = new EventEmitter();
....
loadData() {
    this.loadingChanged.emit(true);
      this.service.readDate()
        .subscribe((data: any) => {
            ........
            this.loadingChanged.emit(false);
        })

  }

最后在childA组件中,我必须接收变量并执行操作

childA.component.ts

@Input() loading: boolean = false
constructor() {
....}
....

在子级A中,我有一个正在运行的加载微调器,但是在控制台中出现错误:

  

错误错误:ExpressionChangedAfterItHasBeenCheckedError:表达   检查后已更改。先前的值:'loading:false'。   当前值:“加载中:true”。

我该如何解决问题? 有关于它的文档(ngAfterViewInit),但我不明白为什么在我的情况下它不起作用。

2 个答案:

答案 0 :(得分:0)

Angular运行更改检测,当发现传递到子组件的某些值已更改时,Angular会引发错误ExpressionChangedAfterItHasBeenCheckedError Read here in detail

要解决您的问题,可以使用 childA.component.ts

中的AfterContentChecked生命周期挂钩
import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }

答案 1 :(得分:0)

  

Imp:Angular,在开发模式下运行两次更改检测。

由于在第一个更改检测阶段中,它确定父组件的加载属性已更改,因此在下一个更改检测周期中,它观察到子组件再次更改了加载属性,因此由于加载而抛出异常在第一个周期检查完所有属性后,属性就更改了。

在生产模式下,您不会收到此错误,因为在生产模式下,更改检测仅运行一次。这就是为什么打开开发模式很重要的原因,这样我们才能提前知道这些类型的错误,这些错误会导致数据和视图之间的不一致。

在setTimeout中放置修改加载属性的代码,以确保在完成上一次更改检测后的下一个刻度中运行该代码。

尝试放置this.loadingChanged.emit(false);在setTimeout中为0。

setTimeout(() => {
 this.loadingChanged.emit(false);
}, 0);