我有一个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.ts
的ngOnInit()
中调用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