她你去两个解决方案!
1.修改ChangeDetectionStrategy到OnPush
对于此解决方案,您基本上是在告诉angular:
停止检查更改;我只会在我知道有必要的时候做
快速修复:
修改您的组件,以便使用 ChangeDetectionStrategy.OnPush
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {
// ...
}
这样,事情似乎不再起作用。这是因为从现在开始,您将必须detectChanges()
手动进行Angular调用。
this.cdr.detectChanges();
这是一个帮助我了解ChangeDetectionStrategy权利的链接:https :
//alligator.io/angular/change-detection-strategy/
2.了解ExpressionChangedAfterItHasBeenCheckedError
这是tomonari_t 答案的一小部分摘录,内容涉及此错误的原因,我尝试仅包括有助于我理解这一部分的部分。
全文显示了有关此处显示的每个点的真实代码示例。
根本原因是角度生命周期的原因:
每次操作后,Angular都会记住用于执行操作的值。它们存储在组件视图的oldValues属性中。
在完成对所有组件的检查之后,Angular然后开始下一个摘要循环,但是不执行操作,而是将当前值与它在上一个摘要循环中记住的值进行比较。
正在摘要循环中检查以下操作:
检查传递给子组件的值是否与现在用于更新这些组件的属性的值相同。
现在检查用于更新DOM元素的值是否与用于更新这些元素的值相同。
检查所有子组件
因此,当比较值不同时,将引发错误。,博客作者Max Koretskyi说:
罪魁祸首始终是子组件或指令。
最后,这是一些通常会导致此错误的现实示例:
可以在此处找到每个样本(plunkr),在我的情况下,问题是动态组件实例化。
另外,根据我自己的经验,我强烈建议每个人都避免使用该setTimeout
解决方案,在我的情况下,它会导致“几乎”无限循环(我不愿意向您展示如何激发它们的21个调用),
我建议始终牢记Angular生命周期,这样您就可以考虑每次修改另一个组件的值时它们将如何受到影响。遇到此错误,Angular会告诉您:
您可能以错误的方式执行此操作,确定您是正确的吗?
同一博客还说:
通常,解决方法是使用正确的更改检测挂钩创建动态组件
对我来说,一个简短的指南是在编码时至少考虑以下两个方面(随着时间的推移,我将尝试对其进行补充):
- 避免从子组件的父组件中修改父组件的值,而是:从其父组件中修改它们。
- 使用
@Input
和@Output
指令时,除非组件已完全初始化,否则请尽量避免触发lyfecycle更改。
- 避免不必要的调用,
this.cdr.detectChanges();
因为它们可能引发更多错误,尤其是在处理大量动态数据时
- 当
this.cdr.detectChanges();
强制使用时,请确保@Input, @Output, etc
在右侧检测钩(OnInit, OnChanges, AfterView, etc
)处填充/初始化正在使用的变量()。
- 如果可能的话,请删除而不是hide,这与第3点和第4点有关。
也
如果您想全面了解Angular Life Hook,建议您在此处阅读官方文档: