我有两个组件:ParentComponent > ChildComponent
和一个服务,例如, TitleService
。更新父组件中父值的值会导致ExpressionChangedAfterItHasBeenCheckedError发生角度
ParentComponent
看起来是这样的:
export class ParentComponent implements OnInit, OnDestroy {
title: string;
private titleSubscription: Subscription;
constructor (private titleService: TitleService) {
}
ngOnInit(): void {
// Watching for title change.
this.titleSubscription = this.titleService.onTitleChange()
.subscribe(title => this.title = title)
;
}
ngOnDestroy(): void {
if (this.titleSubscription) {
this.titleSubscription.unsubscribe();
}
}
}
ChildComponent
看起来是这样的:
export class ChildComponent implements OnInit {
constructor (
private route: ActivatedRoute,
private titleService: TitleService
) {
}
ngOnInit(): void {
// Updating title.
this.titleService.setTitle(this.route.snapshot.data.title);
}
}
的想法很简单:ParentController
显示标题在屏幕上。为了始终呈现其订阅TitleService
的实际标题并监听事件。当标题被改变时,事件发生并且标题被更新。
当加载ChildComponent
时,它从路由器(它会动态解析)获取数据并告知TitleService
用新值更新标题。
问题是这样的解决方案会导致此错误:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Dynamic Title'.
它看起来像值在变化检测一轮更新。
我是否需要重新安排代码以实现更好的实现,还是必须在某处启动另一个更改检测?
我可以移动
setTitle()
和onTitleChange()
调用推崇构造函数,但我读过,它被认为是一种不好的做法做任何“繁重工作”在构造逻辑,除了初始化局部性质。此外,标题应由子组件确定,因此无法从中提取此逻辑。
更新
我已经实现了一个小例子,以便更好地说明这个问题。你可以在the GitHub repository找到它。
<p>Parent Component</p>
<p>Title: "<span *ngIf="title">{{ title }}</span>"</p>
<hr>
<app-child></app-child>
您是否尝试使用ngAfterViewInit代替ParentComponent中的ngOnInit? –
你可以显示你的路线配置吗? –
还有组件模板? –