请向我解释为什么我一直得到这个错误:ExpressionChangedAfterItHasBeenCheckedError:表达式已经改变后,它被检查。
显然,我只有在开发模式下才会遇到这种情况,在我的产品构建中不会出现这种情况,但这非常烦人,而且我根本不明白在我的开发环境中出现错误而不会在prod上显示的好处——可能是因为我缺乏理解。
通常,修复很简单,我只是把导致错误的代码包装在setTimeout中,就像这样:
setTimeout(()=> {
this.isLoading = true;
}, 0);
或者使用如下构造函数强制检测更改:
this.isLoading = true;
this.cd.detectChanges();
但是为什么我总是遇到这个错误呢?我想要了解它,这样我就可以在将来避免这些俗套的修复。
请遵循以下步骤:
1.
通过从@angular/core导入'ChangeDetectorRef'来使用它,如下所示:
import{ ChangeDetectorRef } from '@angular/core';
2.
在constructor()中实现,如下所示:
constructor( private cdRef : ChangeDetectorRef ) {}
3.
添加下面的方法到你的函数,你正在调用的事件,如点击按钮。它看起来是这样的:
functionName() {
yourCode;
//add this line to get rid of the error
this.cdRef.detectChanges();
}
此错误表明应用程序中存在真正的问题,因此抛出异常是有意义的。
在devMode中,更改检测在每次常规的更改检测运行之后增加一个额外的回合,以检查模型是否已更改。
如果模型在常规变化检测轮和附加变化检测轮之间发生了变化,则这表明也发生了变化
变更检测本身导致了变更
每次调用方法或getter都会返回不同的值
这两个都不好,因为不清楚如何继续,因为模型可能永远不会稳定。
如果Angular一直运行变更检测直到模型稳定,那么它可能会一直运行下去。
如果Angular不运行变更检测,那么视图可能不会反映模型的当前状态。
参见Angular2中生产模式和开发模式的区别是什么?
更新
我强烈建议首先从OP的自我响应开始:适当地考虑在构造函数中可以做什么,而在ngOnChanges()中应该做什么。
原始
这与其说是一个答案,不如说是一个题外话,但它可能会帮助到一些人。当我试图让按钮的存在取决于表单的状态时,我偶然发现了这个问题:
<button *ngIf="form.pristine">Yo</button>
据我所知,这种语法会导致根据条件从DOM中添加和删除按钮。这又会导致ExpressionChangedAfterItHasBeenCheckedError。
在我的案例中,解决方案(尽管我没有声称掌握了差异的全部含义)是使用display: none来代替:
<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>