Angularfire2使用*ngFor遍历对象报错求助
解决AngularFire2中*ngFor遍历对象的错误及关联Profile名称的方法
嘿,我来帮你搞定这个问题!你遇到的Cannot find a differ supporting object '[object Object]'错误,核心原因很简单:Angular的*ngFor指令只能遍历数组(Iterable),但你从Firebase获取的items数据是一个键值对形式的对象,不是数组,所以直接用*ngFor就会报错。
接下来我一步步给你讲怎么解决,还能顺便搞定关联Profile名称的需求:
第一步:把Firebase返回的对象转换成数组
Firebase Realtime Database默认返回的是类似{ id1: {...}, id2: {...} }的对象结构,我们需要把它转换成Angular能遍历的数组。推荐用AngularFire2的snapshotChanges()方法,它还能帮我们拿到每个item的Firebase键值:
import { Component } from '@angular/core'; import { AngularFireDatabase } from '@angular/fire/database'; import { Observable } from 'rxjs'; import { map, combineLatest } from 'rxjs/operators'; @Component({ selector: 'app-your-component', templateUrl: './your-component.html' }) export class YourComponent { // 存储转换后的items数组(带Firebase key) private items$: Observable<any[]>; // 存储所有profile数据(键是userId) private profiles$: Observable<{[key: string]: any}>; // 最终合并了username的items数据 itemsWithUsername$: Observable<any[]>; constructor(private db: AngularFireDatabase) { // 转换items为数组 this.items$ = this.db.list('items').snapshotChanges().pipe( map(changes => changes.map(c => ({ key: c.payload.key, // 获取Firebase的item id ...c.payload.val() // 展开item的其他属性(name、type、userId) })) ) ); // 获取所有profile数据,以userId为键 this.profiles$ = this.db.object('profile').valueChanges() as Observable<{[key: string]: any}>; // 合并items和profiles,给每个item添加对应的username this.itemsWithUsername$ = combineLatest([this.items$, this.profiles$]).pipe( map(([items, profiles]) => { return items.map(item => ({ ...item, // 根据item的userId匹配对应的username,找不到就显示Unknown username: profiles[item.userId]?.username || 'Unknown' })); }) ); } }
第二步:在模板中使用*ngFor遍历
现在itemsWithUsername$是一个可观察对象,里面是带username的数组,我们用async管道来订阅它,然后用*ngFor遍历:
<div *ngFor="let item of itemsWithUsername$ | async"> <h3>{{ item.name }}</h3> <p>类型:{{ item.type }}</p> <p>创建者:{{ item.username }}</p> </div>
额外说明
- 如果你用的是
valueChanges()而不是snapshotChanges(),也可以手动转换对象为数组,比如用Object.values(),但这样拿不到Firebase的键值,适合不需要操作item的场景。 - 记得要确保
userId和profile的id是完全匹配的,不然会找不到对应的username。 - 如果你的数据量很大,这种合并方式可能有性能问题,这时候可以考虑在Firebase端做数据嵌套(但要注意Firebase的最佳实践),或者用RxJS的其他操作符优化。
内容的提问来源于stack exchange,提问作者Fajar Kidut
相关产品推荐
相关产品推荐

