Ionic Angular中*ngFor遍历渲染卡片无内容显示问题
问题描述
调用Laravel开发的API接口可正常返回数据,Ionic项目中使用*ngFor循环渲染拉取的用户数据时页面无内容,移除*ngFor指令后静态示例卡片可正常展示。
相关代码
post-list 组件模板
<ion-list> <ion-list-header> Usuarios </ion-list-header> <app-post-item *ngFor=" let item of usaurios" [usuario]="item"> </app-post-item> </ion-list>
post-item 组件模板
<ion-item> <ion-avatar slot="start"> <img src="https://i.pravatar.cc/150?img=2" /> </ion-avatar> <ion-label> <h2>Finn</h2> <h3>I'm a big deal</h3> <p>Listen, I've had a pretty messed up day...</p> </ion-label> </ion-item>
效果参考
- 异常效果:

- 移除
*ngFor=" let item of usaurios" [usuario]="item"后正常效果:
user.service 服务代码
export class UserService { public url: String = environment.url; public usuarios$ = new Subject<Usuario[]>(); public usuario$ = new Subject<Usuario>(); public usuarios: Usuario[] = []; public usuario: Usuario; constructor(public http: HttpClient) {} all$(): Observable<Usuario[]> { return this.usuarios$.asObservable(); } all(): Observable<any> { this.usuarios = []; return this.http.get<Usuario[]>(this.url + 'usuario').pipe( map ((res: any[]) => { Array.from(res).forEach((item: any) => { this.usuario = new Usuario(); this.usuario.set(item); this.usuarios.push(this.usuario); }); this.usuarios$.next(this.usuarios); console.log(res); }) ); } }
post-list.component.ts 组件代码
export class PostListComponent implements OnInit { public usaurios: Usuario[] = []; public usuario: Usuario; public usuarioSubscription = new Subscription(); constructor( public userservice: UserService ) {} ngOnInit() { this.usuarioSubscription = this.userservice.all$().subscribe((res: Usuario[])=>{ this.usaurios = res; }); this.userservice.all().subscribe(res => { console.log('Listo...'); }); } }
控制台输出

post-item.component.ts 组件代码
import { Component, Input, OnInit } from '@angular/core'; import { Usuario } from 'src/app/models/usuario'; @Component({ selector: 'app-post-item', templateUrl: './post-item.component.html', styleUrls: ['./post-item.component.scss'], }) export class PostItemComponent implements OnInit { @Input() usuario: Usuario; constructor() {} ngOnInit() {} }
问题原因与修复方案
核心问题共3处:
- RxJS
map操作符使用错误:pipe(map())必须返回处理后的结果,当前代码中map回调无返回值,导致流发射值为undefined,状态逻辑耦合在map回调中极易出现不一致问题。 - 冗余状态设计:服务层额外维护内部数组+Subject双层状态,多余的中间层容易出现订阅时序、状态重置导致的空值问题。
- 资源泄漏风险:组件中订阅观察对象后未在销毁阶段取消订阅,长期运行会出现内存泄漏。
- 额外问题:post-item模板为全静态内容,未使用传入的
usuario输入属性,即使循环成功也会渲染出完全一致的静态卡片。
修复步骤
- 简化服务层逻辑,移除冗余的Subject和内部状态维护,直接返回转换后的用户数组:
// user.service.ts 修正后 export class UserService { public url: String = environment.url; constructor(public http: HttpClient) {} all(): Observable<Usuario[]> { return this.http.get<any[]>(this.url + 'usuario').pipe( map ((res: any[]) => { return res.map(item => { const usuario = new Usuario(); usuario.set(item); return usuario; }) }) ); } }
- 简化组件逻辑,直接订阅HTTP请求返回的观察对象,补充销毁阶段的取消订阅逻辑,修正变量拼写错误(原变量
usaurios为拼写错误,正确拼写为usuarios):
// post-list.component.ts 修正后 export class PostListComponent implements OnInit, OnDestroy { public usuarios: Usuario[] = []; private usuarioSubscription = new Subscription(); constructor(public userservice: UserService) {} ngOnInit() { this.usuarioSubscription = this.userservice.all().subscribe((res: Usuario[])=>{ this.usuarios = res; }); } ngOnDestroy() { this.usuarioSubscription.unsubscribe(); } }
- 同步修正模板中的循环变量名:
<!-- post-list 组件模板修正后 --> <ion-list> <ion-list-header> Usuarios </ion-list-header> <app-post-item *ngFor="let item of usuarios" [usuario]="item"> </app-post-item> </ion-list>
- 修改post-item组件模板,将静态内容替换为
usuario属性对应的字段,比如:
<ion-item> <ion-avatar slot="start"> <img src="https://i.pravatar.cc/150?img=2" /> </ion-avatar> <ion-label> <h2>{{usuario.name}}</h2> <h3>{{usuario.title}}</h3> <p>{{usuario.description}}</p> </ion-label> </ion-item>
若修正后仍不渲染,优先检查控制台是否有组件未声明、路由配置错误类的报错,移除*ngFor时单个组件可正常显示说明组件本身声明无问题,90%以上场景为数据流逻辑导致的数组为空问题。
内容的提问来源于stack exchange,提问作者John James
相关产品推荐
相关产品推荐

