[英]Change detection for child property in Angular
I have the following Product object inside an Angular application.我在 Angular 应用程序中有以下 Product 对象。 The product contains array of orders and other product information.
该产品包含一系列订单和其他产品信息。
Product.ts产品.ts
export interface Product {
ProductID: number;
ProductName: string;
Orders: Order[]
}
I need to display product information and generate order summary inside a child angular component.我需要在子角度组件中显示产品信息并生成订单摘要。
order-summary.component.ts订单摘要.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订单摘要.component.html
<b>{{_product.ProductName}}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>
I believe every time the product object changes, it will generate the order summary ( generateOrderSummary
) even if the Orders
array hasn't been changed.我相信每次产品对象更改时,即使
Orders
数组没有更改,它也会生成订单摘要( generateOrderSummary
)。 What is a better way to fix this issue?解决此问题的更好方法是什么?
I am thinking of adding another property for Orders[] so I can regenerate summary only when order has been changed.我正在考虑为 Orders[] 添加另一个属性,因此只有在订单更改时我才能重新生成摘要。 However, product already contains orders not sure if it is a good design.
但是,产品已经包含订单,不确定它是否是一个好的设计。
order-summary.component.ts订单摘要.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
}
}
Are there any better solutions?有没有更好的解决方案?
In this case you could skip the setter implementation of the @Input
and use Angular OnChanges
hook with SimpleChanges
parameter.在这种情况下,您可以跳过
@Input
的 setter 实现并使用带有SimpleChanges
参数的 Angular OnChanges
钩子。 It allows you to check if it's the first invoke of the component and compare previous and current values of the @Input
property.它允许您检查它是否是组件的第一次调用,并比较
@Input
属性的先前值和当前值。
Try the following尝试以下
order-summary.component.ts订单摘要.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订单摘要.component.html
<b>{{ product?.ProductName }}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>
I think you could use observables and rxjs logic like this.我认为你可以像这样使用 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
}
}
and subscribe to product in your html并在您的 html 中订阅产品
<div *ngIf="product$ | async as product">
<b>{{product.ProductName}}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.