升级到Angular版本9后,出现一系列错误:“ ExpressionChangedAfterItHasBeenCheckedError:检查表达式后已更改。'hidden'的先前值:'true'。当前值:'false'。” >
这是由我的OverlayService和App-Component之间的交互引起的。当我使用该服务更改overlayOff变量的值时,我的叠加层将启动。我得到了错误。
这不是8.x版中的行为。每次我从服务器对DOM进行更改时,我都会经常在项目中关闭和打开叠加层。有关如何解决此问题的建议。
app.component.html
<div class="container-fluid">
<div [hidden]="overlayOff" id="overlay">
<mp-loading marginTop="25"></mp-loading>
</div>
<router-outlet></router-outlet>
</div>
app.component.ts
@Component({
// tslint:disable-next-line:component-selector
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
private overlaySubscription: Subscription;
overlayOff = true;
constructor({
private overlayService: OverlayService)
}
ngOnInit() {
this.overlaySubscription = this.overlayService.toggleOverlay
.subscribe(nextValue => {
this.overlayOff = (nextValue === undefined) ? !this.overlayOff : nextValue;
// console.log('OverlayOff:' + this.overlayOff);
});
}
ngOnDestroy() {
this.overlaySubscription.unsubscribe();
}
}
overlay.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class OverlayService {
toggleOverlay: Subject<boolean> = new Subject();
constructor() { }
overlayOn() {
// console.log('overlay On');
this.toggleOverlay.next(false);
}
overlayOff() {
this.toggleOverlay.next(true);
}
}
答案 0 :(得分:0)
使用async
管道会更好。这样,您根本就不必使用订阅
<div class="container-fluid">
<div [hidden]="overlayOff$ | async" id="overlay">
<mp-loading marginTop="25"></mp-loading>
</div>
<router-outlet></router-outlet>
</div>
component.ts:
readonly overlayOff$ = this.overlayService.toggleOverlay.pipe(
pairwise(),
map(([prev, next]) => next == null ? !prev : next),
startWith(true)
);
此外,建议使用changeDetectionStrategy OnPush。这是为了防止错误检测可能会发现不必要的更改
答案 1 :(得分:0)
虽然我不知道为什么会发生问题,但似乎对我有用的解决方案如下。
首先在app.component.ts中添加AfterContentChecked生命周期挂钩。
创建一个新的私有变量overlayResponseHolder
下一个更改订阅
.subscribe(nextValue => {
this.overlayResponseHolder = nextValue;
});
创建一个新函数ngAfterContentChecked
ngAfterContentChecked() {
this.overlayOff = this.overlayResponseHolder;
}
不确定是解决方案还是集群,但现在它又可以工作了。