异步管道未更新视图



Repro

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

app.service

创建一个具有一些默认值的BehaviorSubject的简单服务,一个将此主题作为可观察对象返回的函数,最后一个将该主题发出新值的函数。

app.component

该组件只需获取对服务返回的可观察对象的引用,并通过异步管道订阅它。请注意,为了显示发射的值,可观察到的是管道。

此组件还显示第二个组件。

app2.组件

这个组件有一个输入,它订阅了由发出新值的服务返回的可观察结果

问题

问题是,即使我看到控制台中发出的新值,app.component的视图也没有更新。

起初,我认为这是因为服务返回的observable不在区域中,所以我尝试将该函数的某个部分封装到zone.run(observable的全部内容以及接下来的/完整的调用)中,但它仍然不起作用。

有一件事是有效的,那就是app2.component中的注释行,它使用setTimeout订阅observable。

另一件有效的事情是将更改检测策略设置为默认值,而不是OnPush,然而,我不希望这样做

在我看来,app.component获取可观察的内容,并通过异步管道订阅它(因此,它应该在收到新值后立即刷新值,这是可观察的目标,向Angular指示发生了变化)。与此同时,app2.component被加载,并通过其输入更新observable,因此app.component的异步管道应该获得新值并更新其视图,就像它在没有OnPush策略的情况下所做的那样。

我很有信心这不是一个有角度的问题,而是我的误解,但如果有人能解释我错在哪里,我会很感激:-)

注意,我也检查了StackOverflow上的其他线程,但他们都在谈论zone.run或使用detectChanges(我不知道在哪里使用它)

可观察到的新值的发射标志着在下一个变化检测周期中要检查的OnPush组件。但我认为,在您的情况下,根本没有任何事情会触发应用程序中的CD循环。这解释了为什么带有setTimeout的行修复了它:setTimeout触发CD循环,并且因为组件被标记为要检查,所以它被更新。

添加.slice(),angular会刷新。

let objects = this.state.objects.slice();
this.state = {...this.state, objects};

最新更新