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

如何在Angular中增强API返回的JSON对象,避免Client信息重复显示

解决Angular渲染中客户信息重复显示的问题

针对你遇到的同一个客户的多条会员记录重复显示客户信息的问题,我给你两种实用的解决方案,你可以根据实际场景选择:

方案一:预处理数据结构(推荐)

这种方法是先在组件里把原始的JSON数据转换成「客户+旗下所有会员记录」的结构,这样渲染时客户信息自然只会显示一次,逻辑也更清晰。

步骤1:在组件中转换数据

假设你从API获取到的原始数据存在rawClientInfo变量里,你可以用reduce方法聚合数据:

// 组件.ts文件中的代码
rawClientInfo = [
  {"id":998, "client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123}, "membership":{"type":"Semi-Annually","price":18000}, "start_date":"2019-11-19","end_date":"2020-05-16","payment":12000,"balance":0 },
  {"id":1004, "client":{"id":"AF01072","name":"Vivek","lastName":"Joshi","phone":123}, "membership":{"type":"Annually","price":30000}, "start_date":"2020-08-27","end_date":"2021-08-27","payment":30000,"balance":5000 }
];

clientWithMemberships: any[] = [];

ngOnInit() {
  // 聚合数据:按客户ID分组,将同一客户的会员记录归到一起
  const grouped = this.rawClientInfo.reduce((acc, item) => {
    const clientId = item.client.id;
    // 如果该客户还没被加入分组,先创建客户基础信息
    if (!acc[clientId]) {
      acc[clientId] = {
        ...item.client,
        memberships: [] // 新增数组存储该客户的所有会员记录
      };
    }
    // 将当前会员记录加入对应客户的会员列表
    acc[clientId].memberships.push({
      id: item.id,
      type: item.membership.type,
      price: item.membership.price,
      start_date: item.start_date,
      end_date: item.end_date,
      payment: item.payment,
      balance: item.balance
    });
    return acc;
  }, {});

  // 将分组后的对象转为数组,方便模板循环
  this.clientWithMemberships = Object.values(grouped);
}

步骤2:在模板中渲染转换后的数据

现在模板可以先渲染客户信息,再循环渲染该客户的所有会员记录:

<!-- 组件.html文件中的代码 -->
<div *ngFor="let client of clientWithMemberships">
  <!-- 仅显示一次客户核心信息 -->
  <div class="client-header">
    <h3>{{client.name}} {{client.lastName}}</h3>
    <p>客户ID: {{client.id}} | 联系电话: {{client.phone}}</p>
  </div>

  <!-- 循环渲染该客户的所有会员记录 -->
  <div class="membership-item" *ngFor="let membership of client.memberships">
    <p>会员类型: {{membership.type}} | 价格: {{membership.price}}</p>
    <p>有效期: {{membership.start_date}} 至 {{membership.end_date}}</p>
    <p>已支付: {{membership.payment}} | 余额: {{membership.balance}}</p>
    <hr>
  </div>
</div>

方案二:在模板中判断是否显示客户信息

如果你不想修改原始数据结构,可以在模板里通过判断当前记录是否是该客户的第一条,来控制客户信息的显示:

步骤1:添加trackBy方法(优化性能)

在组件中定义一个trackBy方法,帮助Angular高效识别重复的客户:

// 组件.ts文件中的代码
trackByClientId(index: number, item: any): string {
  return item.client.id;
}

步骤2:在模板中添加判断逻辑

利用*ngIf判断当前记录的客户ID是否和上一条不同,只在第一条显示客户信息:

<!-- 组件.html文件中的代码 -->
<div *ngFor="let c of clientinfo; let i = index; trackBy: trackByClientId">
  <!-- 仅在当前客户的第一条记录显示客户信息 -->
  <ng-container *ngIf="i === 0 || clientinfo[i-1].client.id !== c.client.id">
    <div class="client-header">
      <h3>{{c.client.name}} {{c.client.lastName}}</h3>
      <p>客户ID: {{c.client.id}} | 联系电话: {{c.client.phone}}</p>
    </div>
  </ng-container>

  <!-- 显示会员记录信息 -->
  <div class="membership-item">
    <p>会员类型: {{c.membership.type}} | 价格: {{c.membership.price}}</p>
    <p>有效期: {{c.start_date}} 至 {{c.end_date}}</p>
    <p>已支付: {{c.payment}} | 余额: {{c.balance}}</p>
    <hr>
  </div>
</div>

两种方案对比

  • 方案一:数据结构更合理,后续扩展功能(比如查看客户所有会员记录)更方便,推荐用于大多数场景
  • 方案二:无需修改原始数据,适合快速临时解决问题,但逻辑放在模板中,数据量大或逻辑复杂时维护成本较高

如果条件允许,也可以和后端沟通,让API直接返回「客户+会员列表」的聚合结构,这样前端处理会更省心~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:33:12