首页 > 解决方案 > Angular中子属性的更改检测

问题描述

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

产品.ts

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

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

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>

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

我正在考虑为 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
  }
}

有没有更好的解决方案?

标签: angulartypescriptangular2-changedetection

解决方案


在这种情况下,您可以跳过 setter 的实现并使用带有参数的@InputAngularOnChanges钩子。SimpleChanges它允许您检查它是否是组件的第一次调用,并比较@Input属性的先前值和当前值。

尝试以下

order-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
  }
}

order-summary.component.html

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

推荐阅读