请向我解释为什么我一直得到这个错误:ExpressionChangedAfterItHasBeenCheckedError:表达式已经改变后,它被检查。
显然,我只有在开发模式下才会遇到这种情况,在我的产品构建中不会出现这种情况,但这非常烦人,而且我根本不明白在我的开发环境中出现错误而不会在prod上显示的好处——可能是因为我缺乏理解。
通常,修复很简单,我只是把导致错误的代码包装在setTimeout中,就像这样:
setTimeout(()=> {
this.isLoading = true;
}, 0);
或者使用如下构造函数强制检测更改:
this.isLoading = true;
this.cd.detectChanges();
但是为什么我总是遇到这个错误呢?我想要了解它,这样我就可以在将来避免这些俗套的修复。
我在RxJS/Observables和静态模拟数据之间有这个问题。首先,我的应用程序使用静态模拟数据,在我的例子中是数据数组
html是这样的:
*ngFor="let x of myArray?.splice(0, 10)"
我们的想法是只显示myArray中的10个元素。Splice()获取原始数组的副本。据我所知,这在Angular中是完全没问题的。
然后我把数据流改为Observable模式,因为我的“真实”数据来自Akita(一个状态管理库)。这意味着我的html变成:
*ngFor="let x of (myArray$ | async)?.splice(0, 10)"
where myArray$是[was]类型的Observable<MyData[]>,这个模板中的数据操作是导致错误发生的原因。不要对RxJS对象这样做。
更新
我强烈建议首先从OP的自我响应开始:适当地考虑在构造函数中可以做什么,而在ngOnChanges()中应该做什么。
原始
这与其说是一个答案,不如说是一个题外话,但它可能会帮助到一些人。当我试图让按钮的存在取决于表单的状态时,我偶然发现了这个问题:
<button *ngIf="form.pristine">Yo</button>
据我所知,这种语法会导致根据条件从DOM中添加和删除按钮。这又会导致ExpressionChangedAfterItHasBeenCheckedError。
在我的案例中,解决方案(尽管我没有声称掌握了差异的全部含义)是使用display: none来代替:
<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>