如何在不重新呈现整个页面的情况下更新可观察值的一部分?

时间:2018-10-10 20:58:19

标签: angular rxjs rxjs6

我正在尝试尽可能多地使用异步管道,因为我听说这是最佳实践,因为它可以为您管理可观察的订阅。

我的应用程序的非常简化的版本如下所示:

export class OrderDetailComponent implements OnInit {
  order$: Observable<Order>;
  lineItems$: Observable<LineItem>;

  constructor(
    private orderService: OrderService,
    private lineItemService: LineItemService
  ) {}

  ngOnInit() {
    this.order$ = this.getOrders();
    this.lineItems$ = this.getLineItems();
  }

  private getOrders(): Observable<Order> {}
  private getLineItems: Observable<LineItem[]>;
}

然后模板看起来像这样:

<div *ngIf="order$ | async; let order">
  Order#: {{order.ID}}

  Line Items
  <div *ngIf="lineItems$ | async; let lineItems">
    <div *ngFor="let li of lineItems">
        <app-lineitem-card [lineItem]="li"></app-lineitem-card>
    </div>
  </div>

  Order Summary:
  Total: {{order.Total}}
</div>

显然,这是经过简化的,但要点是页面上几乎所有地方都需要顺序,因此我在最外面的div上使用了异步管道。这在第一页加载时效果很好,但是我遇到的情况是我更新了一部分订单,而该订单实际上只影响页面的一小部分,例如order.Total。我知道我可以执行以下操作来更新订单:

this.order$ = this.getOrder()

但这会导致所有组件重新初始化(由于ngIf)。处理这种情况的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

阅读:

https://angular-2-training-book.rangle.io/handout/change-detection/change_detection_strategy_onpush.html

但是这次,我们明确地告诉Angular我们的组件仅取决于其输入,并且它们都是不可变的。然后,Angular假定MovieComponent没有改变,并将跳过对该组件的检查。

解释尽可能少的单词:更改检测策略会影响angular决定何时重新渲染组件的方式。使用默认时,它将遍历所有属性以检查更改(以及其他触发器)。使用 OnPush 时,更改检测将仅对输入参数进行相等性检查,以确定是否需要重新呈现。因此,数据中的任何更改都只会在对象实例发生更改时反映出来。

您需要考虑不变性,并有意识地选择何时克隆对象以触发更新。在处理大量数据的复杂页面上,这确实会对性能产生重大影响。

使用ngrx / store或ngxs可以帮助遵循这种模式。

答案 1 :(得分:0)

说到API方面,为什么没有嵌套 Observable

class Order {
  idThatWillNeverChange: FooType;
  someChangingProperty$: Observable<SomeType>;
}

并非没有可能。您如何精确地保持已加载的Order“有效”(正在接收更新)是另一回事。