在Ionic中展示Firebase嵌套数据出错:所有列表均显示子项
问题分析与解决方案
你的核心问题出在数据关联的错误赋值和HTML模板的取值错误上,具体拆解如下:
1. 数据逻辑的核心错误
你在遍历querySnapshot时,把获取到的listItems赋值给了self.lists.listItems——但this.lists是存储所有列表的数组,你给整个数组添加了listItems属性,这就导致所有列表都会共享这同一个属性值,自然所有list都会显示相同的子项。
正确的逻辑应该是:给数组中的单个list对象单独添加listItems属性,让每个列表自己关联对应的子项数据。
2. 修正后的TS代码
let dbRefLists = firebase.database().ref('lists/'); dbRefLists.on('value', (querySnapshot) => { // 先获取所有lists的基础数据,同时给每个list初始化空的listItems数组 this.lists = Object.keys(querySnapshot.val()).map(key => { return { ...querySnapshot.val()[key], listItems: [] }; }); // 遍历每个list,获取对应的子项并关联到当前list querySnapshot.forEach((data) => { const listId = data.key; // 直接用data.key获取list的唯一标识,比val().id更可靠 // 找到当前遍历到的list在数组中的对应对象 const targetList = this.lists.find(list => list.id === listId); if (targetList) { dbRefLists.child(`${listId}/listItems`).on('value', (snapshotVal) => { if (snapshotVal.val() !== null) { // 把子项数据赋值给当前的targetList,而非整个lists数组 targetList.listItems = Object.keys(snapshotVal.val()).map(key => snapshotVal.val()[key]); } else { // 无数据时清空数组,避免模板报错 targetList.listItems = []; } }); } }); });
3. 修正后的HTML代码
原来的模板中lists.listItems是错误的,应该取当前循环的list对象的listItems属性:
<ul> <li *ngFor="let list of lists; let i=index" text-wrap (click)="toggleGroup(i)" [ngClass]="{active: isGroupShown(i)}"> <h2> <span>{{list.title}}</span> </h2> <ul *ngIf="isGroupShown(i)"> <!-- 这里改成list.listItems,对应单个列表的子项 --> <li *ngFor="let listItem of list.listItems"> <span>{{listItem.title}}</span> </li> </ul> </li> </ul>
额外优化提示
- 如果不需要实时更新数据,可以用
once('value')代替on('value');如果需要实时监听,记得在组件销毁时调用off()取消监听,避免内存泄漏。 - 若数据量较大,可考虑用Firebase的
orderByChild等查询方法优化数据获取效率。
内容的提问来源于stack exchange,提问作者stefan007
相关产品推荐
相关产品推荐

