我的 angular6 项目中有这个控制台错误:错误:表达式更改后它已被检查错误:表达式在检查后已更改。以前的值:"标志:"。当前值:"标志:空"。
这是 TS 组件子组件中的代码
@Input() flag: any;
这是 HTML 组件子组件中的代码
<div *ngIf="flag !== 'ABBONAMENTO_MDA'">
<div class="form-group col-lg-3 col-md-3">
// something else
</div>
</div>
<div *ngIf="flag === 'ABBONAMENTO_MDA'">
<div class="form-group col-lg-3 col-md-3">
// something else
</div>
这是组件父中的代码
<app-repertorio
[flag]="eventoSelezionato" // here i intercept the state of flagMda
</app-repertorio>
假设您有一个父组件 A 和一个子组件 B。A 组件具有名称和文本属性。在其模板中,它使用引用 name 属性的表达式:
template: '<span>{{name}}</span>'
并且它的模板中还有 B 组件,并通过输入属性绑定将 text 属性传递给该组件:
@Component({
selector: 'a-comp',
template: `
<span>{{name}}</span>
<b-comp [text]="text"></b-comp>
`
})
export class AComponent {
name = 'I am A component';
text = 'A message for the child component`;
...
}
因此,这是当 Angular 运行更改检测时发生的情况。它首先检查 A 组件。列表中的第一个操作是更新绑定,以便它将子组件的文本表达式计算为 A 消息,并将其向下传递给 B 组件。它还将此值存储在视图上:
view.oldValues[0] = 'A message for the child component';
然后,它调用列表中提到的生命周期钩子。
现在,它执行第三个操作,并将表达式 {{name}} 计算到文本 I am A 组件。它使用此值更新 DOM,并将评估值放入 oldValues:
view.oldValues[1] = 'I am A component'; 然后 Angular 执行下一个操作,并对子 B 组件运行相同的检查。检查 B 组件后,当前摘要循环就完成了。
如果 Angular 在开发模式下运行,它会运行第二个摘要,执行我上面列出的验证操作。现在想象一下,在 Angular 将子组件的值 A 消息传递给 B 组件并将其存储后,以某种方式将 A 组件上的属性文本更新为更新的文本。因此,它现在运行验证摘要,第一个操作是检查属性文本是否未更改:
AComponentView.instance.text === view.oldValues[0];//false "子组件的消息" === "更新的文本";假 然而,它已经抛出了错误 ExpressionChangedAfterItHasBeenCheckedError。
第三次操作也是如此。如果 name 属性在 DOM 中呈现并存储后进行了更新,我们将得到相同的错误:
AComponentView.instance.name === view.oldValues[1];//false "我是组件" === "更新名称";假
因此,可以通过通过以下方式强制更改检测来解决错误:
ngAfterViewInit() {
this.cd.detectChanges();
}
取自链接:https://indepth.dev/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error/
用一些初始值初始化标志变量应该可以解决这个问题。这也允许为您的组件提供初始状态以回退到,以防通过输入eventoSelezionato
未定义标志值。
@Input() flag: string = 'INITIAL_VALUE';
只需使用钩子AfterViewChecked和angular的ChangeDetectorRef服务。 更改检测器将帮助收集要检查更改的所有视图。
constructor(private cdRef: ChangeDetectorRef) {}
ngAfterViewChecked() {
this.cdRef.detectChanges();
}