从rc1升级到rc4后,我得到以下异常:
Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'
在线研究了这个问题并在阅读完所有内容之后,我仍然不知道如何以“有角度”的方式纠正这个问题(没有超时等)。
我理解再次运行开发模式更改检测时,只是为了确保没有任何更改。我也明白,改变绑定的所有内容都应该触发另一轮变更检测。
我不明白的是为什么 当事件发生时不会自动触发新一轮检测,如何来纠正
我有一个非常简单的用例。最顶层的组件负责显示外部UI。它还包含一个应隐藏/显示的控件。此行为由活动路由组件控制。
子实例化由活动路由(路由器插座)发生,而不是手动。
因此,这个最顶层的组件和所有子组件都在共享服务中订阅了一个eventemitter并发送事件。
最顶级的组件也在它的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);
}
}
ChildComponent
ngOnInit() {
me.apiService.hidePageControls.emit(false);
}
这背后的基本原理是,当用户导航到应用程序的不同部分时,会使用不同的组件。然后,这些组件将事件发送到最顶层的组件以显示/隐藏特定控件。
我已经阅读了这个问题的可能解决方案,包括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);
});
据我所知,由于超时,在额外的开发更改检测运行完成后,这将导致更改检测。我发现这是一个挑剔的解决方案。
如果存在更好的一个,请告诉我。
答案 0 :(得分:1)
我使用几乎相似的方式启用/禁用控制,具体取决于子元素决策。 在角度更新(rc1-> rc4)之前,它就像一个魅力。更新后,组件在首次加载时开始中断。 突破性变化是:
facade:默认情况下将EventEmitter更改为同步(#8761)(e5904f4)
父组件值在子组件的初始化期间完成更改检测轮次后发生更改。
您的问题的修复可能是:
// in apiService
hidePageControls = new EventEmitter(true);
在EventEmitter构造函数中为True将强制它为异步
希望它能提供帮助。
答案 1 :(得分:0)
当角度变化检测导致模型发生变化时,Angular并不感兴趣。
通过更改检测调用 String url = "https://www.google.pt/";
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));
。
您可以使用ngOnInit()
延迟更改,直到更改检测完成。 setTimeout()
导致应用程序范围的更改检测运行,因此无法预测。
您可以使用未通过更改检测调用的其他生命周期回调
据我记得setTimeout()
适用于此案例。
ngAfterViewInit
另一种方法是注入ngAfterViewInit() {
me.apiService.hidePageControls.emit(false);
}
并明确调用更改检测,以使Angular在抛出之前知道更改:
ChangeDetectorRef