You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Angular ngFor指令正确渲染嵌套对象数据?

问题

我有一个包含嵌套对象的productlists数组,想用Angular的ngFor指令在HTML中展示数据,但出现了重复渲染的问题。

数据结构

productlists = [
    {
      productname: 'orange', price:
        [{ small: 20 }, { medium: 30 }, { large: 40 }], gst: 12
    },
    {
      productname: 'lemon', price:
        [{ small: 40 }, { medium: 80 }, { large: 102 }], gst: 20
    },
    {
      productname: 'apple', price:
        [{ small: 40 }, { medium: 80 }, { large: 102 }], gst: 20
    }
];

现有HTML代码

<div style="margin-left: 20rem;">
<div *ngFor="let product of productlists" >

    <p style="color: blue;">Product Name {{product.productname}}</p>

    <div *ngFor="let productprice of product.price">
        Product Price
        <p>Small: {{productprice.small}}</p>
        <p>Medium: {{productprice.medium}}</p>
        <p>Large: {{productprice.large}}</p>
    </div>
    <p>Product GST {{product.gst}}</p>

</div>
</div>

错误渲染效果

每个产品的价格部分会重复渲染三次,每次仅显示一个规格的价格(第一次显示Small,Medium和Large为空;第二次显示Medium,其余为空;第三次显示Large,其余为空),页面出现冗余的空内容和重复的“Product Price”文本。

解决方法

问题根源在于price字段是包含3个独立对象的数组,每个对象仅存储一个规格的价格。用ngFor循环该数组时,会遍历3次,每次只能拿到单个规格的数据,因此出现重复渲染。

方案1:修改数据结构(推荐)

将price改为单个对象,一次性包含所有规格:

productlists = [
    {
      productname: 'orange', 
      price: { small: 20, medium: 30, large: 40 }, 
      gst: 12
    },
    {
      productname: 'lemon', 
      price: { small: 40, medium: 80, large: 102 }, 
      gst: 20
    },
    {
      productname: 'apple', 
      price: { small: 40, medium: 80, large: 102 }, 
      gst: 20
    }
];

对应的HTML代码去掉内层ngFor,直接读取对象属性:

<div style="margin-left: 20rem;">
  <div *ngFor="let product of productlists">
    <p style="color: blue;">Product Name {{product.productname}}</p>
    <div>
      Product Price
      <p>Small: {{product.price.small}}</p>
      <p>Medium: {{product.price.medium}}</p>
      <p>Large: {{product.price.large}}</p>
    </div>
    <p>Product GST {{product.gst}}</p>
  </div>
</div>

方案2:不修改数据结构,合并规格数据

如果无法调整原始数据,可以通过组件内处理或管道合并数据:

方式A:组件内预处理数据

在组件的ngOnInit中合并每个产品的price数组:

ngOnInit() {
  this.productlists = this.productlists.map(product => ({
    ...product,
    price: product.price.reduce((acc, curr) => ({...acc, ...curr}), {})
  }));
}

处理后HTML代码同方案1。

方式B:模板中使用自定义管道

创建合并对象的管道:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'mergeObjects'})
export class MergeObjectsPipe implements PipeTransform {
  transform(arr: any[]): any {
    return arr.reduce((acc, curr) => ({...acc, ...curr}), {});
  }
}

在模块中声明该管道后,模板中使用:

<div style="margin-left: 20rem;">
  <div *ngFor="let product of productlists">
    <p style="color: blue;">Product Name {{product.productname}}</p>
    <div>
      Product Price
      <ng-container *ngIf="product.price | mergeObjects as mergedPrice">
        <p>Small: {{mergedPrice.small}}</p>
        <p>Medium: {{mergedPrice.medium}}</p>
        <p>Large: {{mergedPrice.large}}</p>
      </ng-container>
    </div>
    <p>Product GST {{product.gst}}</p>
  </div>
</div>

内容的提问来源于stack exchange,提问作者Reegan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:10:15