【问题标题】:How can I update part of the value of an observable without re-rendering my whole page?如何在不重新渲染整个页面的情况下更新 observable 的部分值?
【发布时间】:2019-03-15 20:44:56
【问题描述】:

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

我的应用的一个非常简化的版本如下所示:

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)。处理这种情况的正确方法是什么?

【问题讨论】:

  • 您可能正在定义一个太大的组件。例如,最好让OrderDetailComponentOrderIDComponentOrderLineItemsComponentOrderTotalComponent 组成,它们分别封装了您在单个&lt;div&gt; 中定义的内容。此可能提供的优势是,对Order 的任何更改都只会发布到Order*Components 而不会发布其他任何内容。
  • 我知道我的示例并没有真正显示它,但实际上订单详细信息页面由各种组件组成。问题是哑组件仍然在一个大型容器组件中,该组件进行 api 调用并负责在最外层解析数据。我可以让较小的组件进行 api 调用,但这听起来与许多架构最佳实践相矛盾(据说)。展示与容器等。
  • 我认为智能/哑组件架构实现的误称是树的顶部只能有一个智能容器的概念。我个人不相信或坚持这一点,并在需要时创建智能/容器组件。我会尽量避免嵌套智能/容器组件,但在一个页面上,没有理由为什么页眉、内容和页脚不能是三个独立的智能容器,这就是我的回答所建议的。

标签: angular rxjs rxjs6


【解决方案1】:

阅读:

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

但这一次,我们明确告诉 Angular,我们的组件只依赖于它的输入,并且所有输入都是不可变的。然后 Angular 假定 MovieComponent 没有改变,并会跳过对该组件的检查。

用尽可能少的词来解释:变化检测策略会影响 Angular 决定何时重新渲染组件的方式。当使用 Default 时,它将检查所有属性以检查更改(并且还会有其他触发器)。使用 OnPush 时,更改检测只会对您的输入参数进行相等性检查,以确定是否需要重新渲染。因此,只有在对象的实例发生更改时才会反映数据中的任何更改。

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

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

【讨论】:

    【解决方案2】:

    说到 API 方面,为什么不拥有一个嵌套Observable

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

    并非不可能拥有。您如何准确地保持加载的 Order 'alive'(接收更新)是另一回事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      相关资源
      最近更新 更多