Angular中ngFor遍历数组仅显示最后一项问题求助
问题描述
我通过Service将create组件的输入数据传递至check组件,在check组件中把这些数据存储在receipts数组内。当在check页面的表格中使用ngFor遍历该数组时,仅显示数组的最后一项,但控制台打印数组时所有数据均存在,请问问题出在哪里?能否给出解决建议?
相关代码
Check 组件 TS 文件
ngOnInit(): void { console.log("check oninit"); this.subscription(); } receipts: any[] = []; subscription() { this.receiptdataService.behaveiorSubject$.subscribe((res: any)=>{ for (const [key, val] of Object.entries(res)) { console.log(`${key}: ${val} + 2. respo`); } this.receipts.push(res) console.log(this.receipts) }) }
Check 组件 HTML 文件
<h2 class="display-6">Kiállított számlák:</h2> <table class="table"> <tr> <th>ID</th> <th>Vásárló neve</th> <th>Kiállítás dátuma</th> <th>Esedékesség dátuma</th> <th>Tétel neve</th> <th>Komment</th> <th>Ár</th> <tr> <tr *ngFor="let item of receipts" > <td>{{item.name}}</td> <td >{{item.date}}</td> <td >{{item.date2}}</td> <td >{{item.item}}</td> <td >{{item.comment}}</td> <td >{{item.price}}</td> </tr> </table>
服务代码
private sourceBehav = new BehaviorSubject<any>(null); public behaveiorSubject$ = this.sourceBehav.asObservable(); showReceipt(value: any) { this.sourceBehav.next(value) }
Create 组件 TS 文件(数据发出处)
sendData(value: any): void { // for (const [key, val] of Object.entries(value)) { // console.log(`${key}: ${val}`); // } this.receiptdataService.showReceipt(value); }
Create 组件 HTML 文件
<div> <h2 class="display-6">Állítson elő számlát:</h2> <form [formGroup]="receiptform" #save="ngForm" (ngSubmit)="onSubmit(save.value)" action="POST"> <ul> <li> <label for="cusName" class="form-label">Vásárló neve</label> <input formControlName="name" type="text" class="form-control" id="cusName" #nameval> </li> <span *ngIf=" name!.invalid && (name!.dirty || name!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="name!.errors?.['required']"> A név kötelező! </span> <span [ngStyle]="{'color':'red'}" *ngIf="name!.errors?.['pattern']"> Hibás formmátum! </span> </span> <li> <label for="date" class="form-label">Kiállítás dátuma</label> <input formControlName="date" [max]="maxDate" type="date" class="form-control" id="date"> </li> <span *ngIf=" date!.invalid && (date!.dirty || date!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="date!.errors?.['required']"> A dátum kötelező! </span> </span> <li> <label for="date" class="form-label">Esedékesség dátuma</label> <input formControlName="date2" type="date" class="form-control" id="date"> </li> <span *ngIf=" date2!.invalid && (date2!.dirty || date2!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="date2!.errors?.['required']"> A dátum kötelező! </span> </span> <li> <label for="item" class="form-label">Tétel neve</label> <input formControlName="item" type="text" class="form-control" id="item"> </li> <span *ngIf=" item!.invalid && (item!.dirty || item!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="item!.errors?.['required']"> A tétel kötelező! </span> </span> <li> <label for="comment">Komment</label> <textarea formControlName="comment" class="form-control" id="comment"></textarea> </li> <span *ngIf=" comment!.invalid && (comment!.dirty || comment!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="comment!.errors?.['required']"> Kötelező kommentelni! </span> </span> <li> <label for="price">Ár</label> <span style="width:30%" class="input-group mb-3"> <input formControlName="price" type="number" min=1 class="form-control" id="price"> <span class="input-group-text">,-Ft</span> </span> </li> <span *ngIf=" price!.invalid && (price!.dirty || price!.touched)"> <span [ngStyle]="{'color':'red'}" *ngIf="price!.errors?.['required']"> Az árkötelező! </span> </span> <button (click)="sendData(save.value)" [disabled]="!receiptform.valid" type="submit" class=" btn btn-outline-success">Mentés</button> <button routerLink="../subscription" class="mx-3 btn btn-outline-secondary">Visszalépés</button> </ul> </form> </div>
问题原因与解决建议
问题原因
- 表格结构语法错误:Check组件HTML中,表头的
<tr>标签未正确闭合(最后一行写成了<tr>而非</tr>),导致浏览器渲染时表格结构混乱,后续行元素被错误嵌套,最终仅显示最后一条数据。 - 变更检测未触发:数组是引用类型,
push操作不会改变数组的引用地址,若组件使用OnPush变更检测策略,Angular可能无法感知数组变化,导致视图未更新。
解决建议
1. 修复模板结构
将Check组件HTML中表头的<tr>标签正确闭合:
<tr> <th>ID</th> <th>Vásárló neve</th> <th>Kiállítás dátuma</th> <th>Esedékesség dátuma</th> <th>Tétel neve</th> <th>Komment</th> <th>Ár</th> </tr> <!-- 替换原错误的<tr>标签 -->
2. 确保变更检测触发
若修复模板后仍存在问题,可通过以下方式触发变更检测:
- 创建新数组引用:替换
push操作,生成新数组以触发Angular变更检测:this.receipts = [...this.receipts, res]; - 手动触发变更检测:注入
ChangeDetectorRef并调用detectChanges():import { ChangeDetectorRef } from '@angular/core'; constructor(private cdr: ChangeDetectorRef) {} subscription() { this.receiptdataService.behaveiorSubject$.subscribe((res: any)=>{ this.receipts.push(res); this.cdr.detectChanges(); // 手动触发视图更新 console.log(this.receipts); }); }
3. 额外优化建议
- 定义类型接口:避免使用
any类型,定义收据数据接口提升代码可维护性:interface Receipt { name: string; date: string; date2: string; item: string; comment: string; price: number; } receipts: Receipt[] = []; - 取消订阅防止内存泄漏:组件销毁时取消BehaviorSubject的订阅:
import { Subscription } from 'rxjs'; private subscription!: Subscription; subscription() { this.subscription = this.receiptdataService.behaveiorSubject$.subscribe((res: Receipt)=>{ this.receipts = [...this.receipts, res]; }); } ngOnDestroy(): void { this.subscription.unsubscribe(); }
内容的提问来源于stack exchange,提问作者Rebeka Süveges
相关产品推荐
相关产品推荐

