使用 OnPush 策略进行变化检测的意外行为

Unexpected behaviour of change detection with OnPush strategy

我遇到过非常奇怪的变化检测器行为(使用 OnPush)。我什至无法向自己解释,也不知道如何解决。尽管如此,我还是在 stackblitz

上用非常简单的示例重现了这种行为

https://stackblitz.com/edit/angular-h28cw8

共有三个组件:主要app组件、data组件和loading indicator组件。当用户点击Go to data link 时,Main 组件可以通过<router-outlet> 显示data 组件。还有服务(又名应用程序状态)。当用户单击 Go to data 时,data 组件请求此服务获取数据,加载时有一些延迟。为了模拟这种延迟,我使用了 rxjs 定时器,但是 HttpClient 的行为是完全相同的。数据和加载值通过使用 async 管道进行绑定。但由于某种原因,数据按预期显示,但 loading 不是(最好说它有时有效,但并非总是有效)。这导致加载指示器没有出现在屏幕上。我还将值记录到控制台,在那里很容易看到 loading$ observable 发出值,但 @Input 绑定由于某种原因不起作用。为什么会这样,如何解决?

它不起作用的原因是因为您在检查父组件后从子组件发出 this._loading.next(true) 值。

异步管道会触发订阅并且按预期工作,即运行s cdRef.markForCheck();。但它 不会 运行 更改检测,而只是标记要检查的组件,其中使用了 AsyncPipe 。一旦新的更改检测周期开始,您的组件将识别输入更改。

要修复它,您可以将 this._common.getData() 包装在子组件的微任务中

Promise.resolve().then(() => {
   this._common.getData();
});

Forked Stackblitz