Angular中如何基于API返回的图片名去重渲染图片?
看起来你是想解决Angular中渲染部件图片时重复显示的问题——因为多个部件共享同一张图,现在用*ngFor遍历所有数据导致同一张图重复出现。我看了你在filterDrop里尝试的排序逻辑,其实那不是正确的去重方式(sort是用来排序的,而且你在sort里创建的局部数组根本没法保存去重后的结果),下面给你几个实用的实现思路和代码方案:
方案一:仅在图片首次出现时显示(保留原有行结构)
如果你想保留原来的每行一个部件的结构,但相同图片只在第一次出现时显示,后续行隐藏图片,可以这样做:
在组件中给每个部件添加显示标记
在filterDrop方法里,用Set跟踪已经出现过的图片,给每个部件对象增加一个showImage属性,标记是否需要显示图片:filterDrop() { this.dataDiam1 = this.dataDynParts; let dynDiam1 = this.dataDiam1.map(obj => obj.diam[0]); dynDiam1 = dynDiam1.filter((v, i) => dynDiam1.indexOf(v) === i); this.dataDiam1 = dynDiam1; this.dataDiam2 = this.dataDynParts; let dynDiam2 = this.dataDiam2.map(obj => obj.diam[1]); dynDiam2 = dynDiam2.filter((v, i) => dynDiam2.indexOf(v) === i); this.dataDiam2 = dynDiam2; this.requiredFields(); this.filteredWithDiam = this.dataDynParts; // 新增:处理图片显示标记 const seenImages = new Set<string>(); this.selectedDiam = this.dataDynParts.map(item => { const showImage = !seenImages.has(item.part_image); if (showImage) { seenImages.add(item.part_image); } // 扩展原对象,添加showImage属性 return { ...item, showImage }; }); }在模板中根据标记控制图片显示
修改HTML里的img标签,用*ngIf判断是否显示:<div class="products"> <div class="d-flex flex-row linesColor" *ngFor="let products of selectedDiam"> <img *ngIf="products.showImage" [src]="photosPath + products.part_image" alt="部件图片"> <a class="flex1">{{products.diam}}</a> <a class="flex1">{{products.price1}}</a> <a class="flex1 mb-1"> <input [ngModel]="products.longueur" (ngModelChange)="postQuotationDatas($event,products,'longueur')" class="number" type="number"> </a> <a class="flex1">Total</a> </div> </div>
方案二:按图片分组渲染(图片仅显示一次,下方列出对应所有部件)
如果你想更清晰地组织视图——同一张图片只显示一次,下面列出所有使用该图片的部件,可以按图片分组:
在组件中按图片分组数据
新增一个groupedParts数组,用来存储分组后的图片和对应部件:// 组件类中新增属性 groupedParts: { image: string, parts: any[] }[] = []; filterDrop() { // ... 保留你原来的其他代码 // 新增:按part_image分组数据 const imageGroups: { [key: string]: any[] } = {}; this.dataDynParts.forEach(part => { const imgKey = part.part_image; // 处理空图片的情况,避免无意义分组 if (!imgKey) return; if (!imageGroups[imgKey]) { imageGroups[imgKey] = []; } imageGroups[imgKey].push(part); }); // 转换为数组格式,方便模板遍历 this.groupedParts = Object.entries(imageGroups).map(([image, parts]) => ({ image, parts })); }在模板中渲染分组后的内容
先渲染图片,再遍历该图片对应的所有部件:<div class="products"> <!-- 遍历每个图片组 --> <div *ngFor="let group of groupedParts"> <!-- 显示一次图片 --> <div class="d-flex flex-row linesColor"> <img [src]="photosPath + group.image" alt="部件图片"> <a class="flex1">对应部件列表</a> </div> <!-- 显示该图片下的所有部件 --> <div class="d-flex flex-row linesColor" *ngFor="let product of group.parts"> <a class="flex1">{{product.diam}}</a> <a class="flex1">{{product.price1}}</a> <a class="flex1 mb-1"> <input [ngModel]="product.longueur" (ngModelChange)="postQuotationDatas($event,product,'longueur')" class="number" type="number"> </a> <a class="flex1">Total</a> </div> </div> </div>
方案三:直接生成去重的图片数组(仅渲染图片,不关联部件)
如果你只需要单独渲染所有不重复的图片,不需要和部件关联,可以直接生成去重的图片数组:
// 组件类中新增属性 uniquePhotos: string[] = []; filterDrop() { // ... 保留你原来的其他代码 // 生成去重的图片数组,过滤空值 this.uniquePhotos = [...new Set(this.dataDynParts.map(item => item.part_image))].filter(img => img); }
模板中遍历这个数组:
<div class="products"> <div class="d-flex flex-row linesColor" *ngFor="let photo of uniquePhotos"> <img [src]="photosPath + photo" alt="部件图片"> </div> </div>
小提示
- 确保
part_image字段的值是准确的(比如没有大小写差异、空格等,否则Set会认为是不同的图片),如果有格式问题,可以在map的时候统一处理(比如item.part_image.trim().toLowerCase())。 - 如果你用的是Angular 14+,可以考虑用
trackBy优化*ngFor的性能,避免不必要的DOM重渲染。
内容的提问来源于stack exchange,提问作者Zephyr
相关产品推荐
相关产品推荐

