使用 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();
});
我遇到过非常奇怪的变化检测器行为(使用 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();
});