我在Angular 6应用程序中遇到问题:
假设我有两个组成部分:父母和孩子。
孩子有2个输入。当1个输入发生更改时,子组件在ngOnChanges()内向父组件发出东西。
然后,父组件更改子组件的第二个输入。我希望子组件的更改检测会再次被调用-但不是。子组件的视图显示第二个输入的旧值。
该应用程序具有以下定义:
为了说明这种情况,我创建了一个简单的演示项目。那里我不使用存储,所以我没有任何选择器..相反,我使用rxjs Subject来使用异步管道。
这里是:
https://angular-ccejq4.stackblitz.io
查看控制台以了解发生的情况和时间。
我已经尝试过的:
我发现新值到达异步管道。然后异步管道调用markForCheck()。但它不会调用detectChanges()..因此,更改检测周期将不会运行。仅在下一个更改检测周期中,视图才会正确更改-正如您在我的演示应用程序上看到的那样。
有什么想法吗?
谢谢!
[我先说,是一个很好的细节问题,而且解释清楚。您确实遇到了角度变化检测的警告。
[在ngOnChanges
内部,没有直接的方法来触发另一个更改检测。否则,您将有可能陷入困境。同样在性能方面,他们不允许这样做。您需要找到一种进入下一个JS执行周期的方法
setTimeout
不是克服这个问题的不错选择。您可以将其放在发射周围:
setTimeout(() => this.secondEmitter.emit(this.first));
或者您可以将其置于markForCheck
通话周围:
setTimeout(() => this.cdRef.markForCheck());
但是我同意你的看法,这有点让人讨厌,但有时您只需要解决它。如果您真的无法做到,那还有另一种方法。您的BehaviorSubject
本质上是同步可观察的。但是,您可以在模板中进行async
订阅,以使用asyncScheduler
:
private second = new BehaviorSubject(0);
readonly second$ = this.second.asObservable().pipe(
observeOn(asyncScheduler)
)
constructor() {
this.second.next(0);
this.second$.subscribe((lastval) => {
console.log(`second subscription update to ${lastval}`);
});
}
从最后一个选项开始,我为您的stack作了分叉>
这将使对它的所有订阅在下一个事件循环周期之后都收到消息。