表达式已更改之后已检查错误:表达式在检查后已更改。以前的值:"ngIf: true"。当前值:'ngIf: false'



我有一个Angular 10应用程序,我正试图从登录组件中删除导航组件,所以我在导航组件上创建了一个服务。组件包含以下代码:

visible: boolean;
constructor() {
this.visible = true;
}
show() {
this.visible = true;
}
hide() {
this.visible = false;
}
toggle() {
this.visible = !this.visible;
}
doSomethingElseUseful() { }

在导航组件内部,我输入:

export class NavsideComponent implements OnInit {

constructor(public sr: ServService ) { }
ngOnInit(): void {

}

Html组件:

<div *ngIf="sr.visible">
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav mode="push" class="app-sidenav" opened>
<mat-toolbar class="co">
<span class="toolbar-filler"></span>
.
.
.
.
.
. </div>

但是显示了这个错误:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.

编辑1

登录组件.ts

import { Component, OnInit } from '@angular/core';
import { ServService } from '../../navside/serv.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor( private sr :ServService) { }
ngOnInit(): void {
this.sr.hide();
this.sr.doSomethingElseUseful();
}
}

编辑2

Stacklitz将上面的片段放在一起,可以看到警告:

https://stackblitz.com/edit/angular-ivy-vbkytu?file=src/app/login/login.component.ts

我编辑了您的帖子,其中包含了一个Stacklitz,其中包含报告错误的最小可复制示例。我建议您在下一篇文章中包含一个可重复的最小示例,因此您更有可能得到答案。

关于ExpressionChangedAfterIt HasBeenCheckedError警告

这篇文章有关于这个警告的有用信息:表达式___在检查后发生了变化

在您的特定情况下,会显示警告ExpressionChangedAfterItHasBeenCheckedError,因为sr.visible的值在初始化过程中更改了两次:

  • 在服务SerService创建期间
  • 当您呼叫sr.hide()时,再次在loginComponent.ngOnInit()

在同一轮更改检测中,绑定在视图中的值(sr.visible绑定在<div *ngIf="sr.visible">中(不应该多次更改值,这就是发出警告的原因。

解决在正确组件中调用cdr.changeDetection((的问题

您可以解决调用cdr.detectChanges()以触发第二轮更改检测的问题。但要实现这一点,您需要在具有受影响绑定的组件中调用它。

LoginComponent调用cdr.detectChanges((没有任何效果,因为<div *ngIf="sr.visible">的绑定不在该组件中。您应该在绑定所在的父组件中调用cdr.detectChanges((。

也就是说,在LoginComponent中使用cdr.detectChanges((不会解决问题

export class LoginComponent {
constructor(private sr: ServService, private cdr: ChangeDetectorRef) {}

ngOnInit() {
this.sr.hide();
this.sr.doSomethingElseUseful();

//code bellow will NOT SOLVE the problem:
this.cdr.detectChanges();
}
}

解决问题的方法是在具有绑定<div *ngIf="sr.visible">的组件上调用cdr.detectChanges((。

在我的工作堆栈中(在这个答案的末尾(,该组件是AppComponent:

app.component.html:

<div *ngIf="sr.visible">
Toolbar here
<!-- your mat-side-nav and mat-toolbar here -->
</div>
<app-login></app-login>

因此,在app.component.tsngOnInit()中调用cdr.detectChanges()

export class AppComponent {
constructor(public sr: ServService, 
private cdr: ChangeDetectorRef) {}

ngOnInit() {
this.cdr.detectChanges();
}
}

工作版本-stackblitz

在正确的组件中调用detectChanges的工作版本在以下Stacklitz:中可用

https://stackblitz.com/edit/angular-ivy-nbb7bz?file=src/app/app.component.ts

最新更新