在从rc1升级到rc4后,我遇到了以下异常:
Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'
在网上研究并阅读了所有相关内容之后,我仍然不知道如何以“angular”方式(无需使用timeout等)解决这个问题。
我明白当开发模式更改检测时会再次运行,只是为了确保没有改变的内容。我也知道所有更改绑定的操作都应该触发另一轮更改检测。
我不明白的是为什么事件发生时没有自动触发新的检测轮回以及如何来纠正它。
我有一个非常简单的用例。最上层的组件负责显示外部用户界面,它还包含一个控件,应该被隐藏/显示。此行为由活动路由组件控制。
子级实例化由活动路由(router-outlet)而不是手动执行。
因此,此最上层组件和所有子组件都订阅了共享服务中的一个事件发射器并发送事件。
最上层组件还在其OnInit上订阅此事件。当它接收到事件时,它会更改一个本地变量。这反映在此组件的html上。
AppComponent
export class AppComponent implements OnInit {
hidePageControls:boolean = true;
constructor(private apiService: ApiService) {}
ngOnInit(): any {
let me = this;
this.apiService.hidePageControls.subscribe(value => me.hidePageControls = value);
}
}
子组件
ngOnInit() {
me.apiService.hidePageControls.emit(false);
}
这样做的原理是当用户导航到应用程序的不同部分时,使用不同的组件。这些组件然后向顶层组件发送事件以显示/隐藏特定控件。
我已经阅读了可能的解决方案,包括setTimeout(),直接调用变更检测等。人们也说我们不应该“与框架对抗”,我同意这种看法。
因此,请告诉我在Angular中,子组件通知父组件的想法是否是“错误”的思考方式,并让我知道如何以“Angular”的方式执行此操作。
编辑
我找到的唯一解决此类错误的方法是使用setTimeout(),如下所示:
分离变更检测器。 当事件被触发时,手动触发变更检测轮。
constructor(private apiService: ApiService, private categoryService: CategoryService, private router: Router, private cd: ChangeDetectorRef) {
this.cd.detach();
}
.
.
.
.
this.apiService.hidePageControls.subscribe(value => {
me.hidePageControls = value;
setInterval(() => {
me.cd.detectChanges();
}, 100);
});
据我理解,由于超时而进行的额外开发变更检测运行结束后,这将导致一轮变更检测。我认为这是一个琐碎的解决方案。
如果有更好的解决方案,请告诉我。