ExpressionChangedAfterItHasBeenCheckedError` 错误 angular 4
ExpressionChangedAfterItHasBeenCheckedError` error angular 4
我正在尝试从事一个包含多个组件的项目。示例应用程序是 here。我在开发模式下遇到如下错误
我知道为什么会出现这个错误
Because after the child component values are bound , parent component
values are updated by grandparent component, resulting in throwing of
error during angular dirty check
我的应用程序的骨架是 here。有人可以帮我解决这个问题吗?我知道可以通过使用 setTimeout 或 changeDetectionRef 来解决。但这不是我正在寻找的解决方案,我想知道我在生命周期挂钩期间做错了什么。提前致谢。
很高兴听到您反对 setTimeout
并手动调用 detectChanges
。
我知道这在您的应用程序结构中很明显,但这里有一个示例向您展示了错误的来源:
Because after the child component values are bound , parent component
values are updated by grandparent component, resulting in throwing of
error during angular dirty check
看来你是对的,你的 child 组件在 ngAfterContentInit 发生之前呈现。
Angular 应用程序是一棵视图树。当 angular 运行变化检测机制时,它会遍历这个视图树并为每个视图调用 checkAndUpdateView 函数。
在执行此函数期间,angular 以严格定义的顺序调用其他函数。在我们的案例中,我们对这些函数感兴趣:
execEmbeddedViewsAction
callLifecycleHooksChildrenFirst (AfterContentInit)
execComponentViewsAction
表示angular会在执行ngAfterContentInit
hook之前调用嵌入式视图的变更检测周期(ng-template
生成嵌入式视图) .这就是您的示例中发生的情况:
正如我们在上图中看到的,当 angular 检查 AppComponent 视图时,它首先检查嵌入的视图,然后为 GrandParentComponent
调用 ngAfterContentInit
并下降到 GrandParentComponent
查看。
看来有很多方法可以解决。我在这个 Demo
中试穿了其中的一些
关键时刻不是使用 ngAfterContentInit
钩子而是在 ParentComponent
:
中设置索引和活动值
parent.component.ts
export class ParentComponent {
private _active: boolean = false;
public index = 0;
constructor(
@Host() @Inject(forwardRef(() => GrandParentComponent))
public grandParentComponent: GrandParentComponent) {
this.index = this.grandParentComponent.parents.length;
this.grandParentComponent.parents.push(this)
}
ngOnInit() {
this.active = this.index == this.grandParentComponent.currentStep;
}
ngOnDestroy() {
if (this.grandParentComponent) {
this.grandParentComponent.parents = this.grandParentComponent.parents.filter(x => x !== this);
}
}
其中 parents 属性 已在 GrandParentComponent
中声明:
盛大parent.component.ts
export class GrandParentComponent {
parents = [];
我正在尝试从事一个包含多个组件的项目。示例应用程序是 here。我在开发模式下遇到如下错误
我知道为什么会出现这个错误
Because after the child component values are bound , parent component values are updated by grandparent component, resulting in throwing of error during angular dirty check
我的应用程序的骨架是 here。有人可以帮我解决这个问题吗?我知道可以通过使用 setTimeout 或 changeDetectionRef 来解决。但这不是我正在寻找的解决方案,我想知道我在生命周期挂钩期间做错了什么。提前致谢。
很高兴听到您反对 setTimeout
并手动调用 detectChanges
。
我知道这在您的应用程序结构中很明显,但这里有一个示例向您展示了错误的来源:
Because after the child component values are bound , parent component values are updated by grandparent component, resulting in throwing of error during angular dirty check
看来你是对的,你的 child 组件在 ngAfterContentInit 发生之前呈现。
Angular 应用程序是一棵视图树。当 angular 运行变化检测机制时,它会遍历这个视图树并为每个视图调用 checkAndUpdateView 函数。
在执行此函数期间,angular 以严格定义的顺序调用其他函数。在我们的案例中,我们对这些函数感兴趣:
execEmbeddedViewsAction
callLifecycleHooksChildrenFirst (AfterContentInit)
execComponentViewsAction
表示angular会在执行ngAfterContentInit
hook之前调用嵌入式视图的变更检测周期(ng-template
生成嵌入式视图) .这就是您的示例中发生的情况:
正如我们在上图中看到的,当 angular 检查 AppComponent 视图时,它首先检查嵌入的视图,然后为 GrandParentComponent
调用 ngAfterContentInit
并下降到 GrandParentComponent
查看。
看来有很多方法可以解决。我在这个 Demo
中试穿了其中的一些关键时刻不是使用 ngAfterContentInit
钩子而是在 ParentComponent
:
parent.component.ts
export class ParentComponent {
private _active: boolean = false;
public index = 0;
constructor(
@Host() @Inject(forwardRef(() => GrandParentComponent))
public grandParentComponent: GrandParentComponent) {
this.index = this.grandParentComponent.parents.length;
this.grandParentComponent.parents.push(this)
}
ngOnInit() {
this.active = this.index == this.grandParentComponent.currentStep;
}
ngOnDestroy() {
if (this.grandParentComponent) {
this.grandParentComponent.parents = this.grandParentComponent.parents.filter(x => x !== this);
}
}
其中 parents 属性 已在 GrandParentComponent
中声明:
盛大parent.component.ts
export class GrandParentComponent {
parents = [];