Nao*_*mor 5 rxjs ngrx angular2-changedetection angular angular-changedetection
我在使用 Angular 6 应用程序时遇到问题:
假设我有 2 个组件:父组件和子组件。
孩子有2个输入。当 1 个输入发生变化时,在 ngOnChanges() 中,子组件向父组件发出一些东西。
然后父组件更改子组件的第二个输入。我希望再次调用子组件的更改检测 - 但事实并非如此。子组件的视图显示了第二个输入的旧值。
该申请有以下定义:
为了说明这个案例,我创建了一个简单的演示项目。在那里我不使用商店,所以我没有任何选择器......相反,我使用 rxjs Subject 来使用异步管道。
这里是:
https://angular-ccejq4.stackblitz.io
查看控制台以了解会发生什么以及何时发生。
我已经尝试过的:
我发现新值到达异步管道。然后异步管道调用 markForCheck()。但它不会调用detectChanges()..所以更改检测周期不会运行。视图只会在下一个更改检测周期时正确更改 - 正如您在我的演示应用程序中看到的那样。
有任何想法吗?
谢谢!
首先我要说的是,这是一个很好的问题,详细且解释得很好。您确实遇到了角度变化检测的警告。
从内部ngOnChanges没有直接的方法来触发另一个变化检测。否则你将有可能陷入循环。此外,在性能方面他们也不允许这样做。你需要想办法进入JS的下一个执行周期
setTimeout克服这个问题并不是一个坏的选择。您可以将其放在发射周围:
setTimeout(() => this.secondEmitter.emit(this.first));
Run Code Online (Sandbox Code Playgroud)
或者你可以把它放在markForCheck通话中:
setTimeout(() => this.cdRef.markForCheck());
Run Code Online (Sandbox Code Playgroud)
但我同意你的观点,这感觉有点老套,但有时你只需要应对它。如果实在不行的话,还有别的办法。你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}`);
});
}
Run Code Online (Sandbox Code Playgroud)
从上一个选项开始,我已经对你的堆栈进行了分叉
这将使任何对其的订阅在下一个事件循环周期后收到消息。
更新
回到这一点,更好的解决方案是使用async创建EventEmitter.
在这种情况下,您可以.emit在第二个可观察量上使用:
@Output() firstEmitter:EventEmitter<number> = new EventEmitter();
// notice the 'true'
@Output() secondEmitter:EventEmitter<number> = new EventEmitter(true);
ngOnChanges(changes:any) {
if (changes.first) {
this.secondEmitter.emit(this.first);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
602 次 |
| 最近记录: |