【问题标题】:ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'ngIf: true'。当前值:'ngIf: false'
【发布时间】:2021-01-31 17:20:39
【问题描述】:

我有一个 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

Login.component.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

Stackblitz 将上面的 sn-ps 放在一起,可以看到警告:

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

【问题讨论】:

  • 你在任何地方调用 sr.show() 吗?
  • 我在登录组件调用 sr.hide()
  • 您可以编辑您的帖子并包含登录 component.ts 代码吗?
  • 完成,我已经添加了
  • 感觉像this.cdr.detectChanges(); 上的ngOnInit() 可以解决这里描述的问题:stackoverflow.com/questions/34364880/…

标签: javascript html angular


【解决方案1】:

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

关于 ExpressionChangedAfterItHasBeenCheckedError 警告

这篇文章有关于这个警告的有用信息:Expression ___ has changed after it was checked

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

  • 服务期间有一次SerService创建和
  • 再次拨打loginComponent.ngOnInit()sr.hide();

在同一轮更改检测中,绑定在视图中的值(sr.visible 绑定在&lt;div *ngIf="sr.visible"&gt;)不应多次更改值,这就是警告的原因。

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

您可以调用cdr.detectChanges() 来解决问题,以便触发第二轮变更检测。但要使其正常工作,您需要在具有受影响的绑定的组件中调用它。

LoginComponent 上调用 cdr.detectChanges() 没有无效,因为 &lt;div *ngIf="sr.visible"&gt; 的绑定不在该组件中。您应该在绑定所在的父组件中调用 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();
      }
    }

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

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

app.component.html:

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

所以,cdr.detectChanges()app.component.tsngOnInit() 中被调用:

    export class AppComponent {
      constructor(public sr: ServService, 
        private cdr: ChangeDetectorRef) {}
    
      ngOnInit() {
        this.cdr.detectChanges();
      }
    }

工作版本 - stackblitz

在右侧组件中调用 detectChanges 的工作版本在以下 Stackblitz 中可用:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-18
    • 2019-02-03
    • 2019-05-22
    • 2020-01-07
    • 2017-09-16
    • 1970-01-01
    • 2018-01-10
    • 2020-06-16
    相关资源
    最近更新 更多