Angular 中 child 属性 的更改检测

Change detection for child property in Angular

我在 Angular 应用程序中有以下产品 object。该产品包含一系列订单和其他产品信息。

Product.ts

export interface Product { 
    ProductID: number;
    ProductName: string;
    Orders: Order[]
}

我需要在 child angular 组件中显示产品信息并生成订单摘要。

order-summary.component.ts

export class OrderSummary {

  _product: Product;
  @Input() set product(value: Product) {
    this._product = value;
    this.generateOrderSummary(value.Orders);
  }

  private generateOrderSummary(orders: Order[]) {
   // Logic to generate order summary
  }

}

order-summary.component.html

<b>{{_product.ProductName}}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>

我相信每次产品 object 更改时,即使 Orders 数组未更改,它也会生成订单摘要 (generateOrderSummary)。解决此问题的更好方法是什么?

我正在考虑为 Orders[] 添加另一个 属性,这样我就可以仅在更改订单时重新生成摘要。但是,产品已经包含订单,不确定它是否是一个好的设计。

order-summary.component.ts

export class OrderSummary {
  _product: Product;
  @Input() set product(value: Product) {
    this._product = value;
  }

  @Input() set orders(value: Orders[]) {
    this.generateOrderSummary(value.Orders);
  }

  private generateOrderSummary(orders: Order[]) {
   // Logic to generate order summary
  }
}

有没有更好的解决方案?

在这种情况下,您可以跳过 @Input 的 setter 实现并使用 Angular OnChanges hook with SimpleChanges 参数。它允许您检查它是否是组件的第一次调用,并比较 @Input 属性.

的先前值和当前值

尝试以下方法

顺序-summary.component.ts

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

export class OrderSummary implements OnChanges {
  @Input() product: Product;

  ngOnChanges(changes: SimpleChanges) {
    if (!!changes.product) {
      if (changes.product.firstChange) {                 // <-- first time the component is rendered
        this.generateOrderSummary(this.product.orders);  // <-- could also be `changes.product.currentValue.orders`
      } else if (                                        // <-- true only if different `orders` value
        !!changes.product.previousValue &&
        !!changes.product.previousValue.orders &&
        changes.product.previousValue.orders !== changes.product.currentValue.orders
      ) {
        this.generateOrderSummary(product.orders);
      }
    }
  }

  private generateOrderSummary(orders: Order[]) {
    // Logic to generate order summary
  }
}

顺序-summary.component.html

<b>{{ product?.ProductName }}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>

我想你可以像这样使用 observables 和 rxjs 逻辑。

export class OrderSummary implements OnInit {
  product$: Observable<Product>;
  private productSubject$ = new Subject();

  @Input() set product(value: Product) {
    this.productSubject$.next(value);
  }
  
  ngOnInit(): void {
    this.product$ = this.productSubject$.pipe(
          distinctUntilChanged((prev: Product, curr: Product) => prev.ProductId === curr.ProductId), 
          map(prod => {
             this.generateOrderSummary(prod.orders);
             return prod;
          })
  }


  private generateOrderSummary(orders: Order[]) {
   // Logic to generate order summary
  }

}

并在您的 html

中订阅产品
<div *ngIf="product$ | async as product">
   <b>{{product.ProductName}}</b>
   <b> ... show other product details </b>
   <table> ... show generated order summary ... </table>
</div>