Angular 2中Firebase数据获取与表格渲染问题求助
解决Angular 2中Firebase数据检索与表格填充问题
我来帮你一步步拆解解决这两个问题,从数据结构优化到代码实现逐一梳理:
一、无法通过密钥检索Firebase数据的解决方案
先看你提供的Firebase数据结构,EDI855下的Bill To、Email Id、Po Number是三个独立节点,每个节点下的子项都有自动生成的唯一密钥(比如-L9ac7clRzSVT-EfGxYv)。要通过这些密钥获取对应数据,你可以用AngularFire2的object方法精准定位节点:
1. 单个密钥数据检索(以Bill To为例)
先确保你已导入AngularFireDatabase并注入到组件中:
import { AngularFireDatabase } from 'angularfire2/database'; constructor(private db: AngularFireDatabase) {} // 根据密钥获取单个Bill To数据 getSingleBillTo(key: string) { return this.db.object(`/EDI855/Bill To/${key}`).valueChanges(); } // 在组件中调用并订阅数据 ngOnInit() { this.getSingleBillTo('-L9ac7clRzSVT-EfGxYv').subscribe(data => { console.log('Bill To数据:', data); // 输出"123456789" }); }
2. 关键优化:调整数据结构
你当前的结构把同一笔订单的三个字段拆分在不同节点,会导致后续关联数据、填充表格非常麻烦。更合理的做法是把每笔订单的所有字段放在同一个节点下,比如:
EDI855 -L9ac7clRzSVT-EfGxYv: billTo: "123456789" emailId: "test@gmail.com" poNumber: "123456789" -L9acDp2k34qDpubJFr6: billTo: "123456780" emailId: "test1@gmail.com" poNumber: "VV002"
这样不仅能通过单个密钥直接获取整笔订单的所有数据,还能大幅简化表格填充逻辑。
二、遍历Firebase数据填充表格的解决方案
你说console能看到数据但表格不显示,大概率是异步数据处理不恰当或者模板绑定逻辑有误,下面分两种结构给出解决方案:
方案1:基于你当前的数据结构(不调整结构)
因为三个字段的子节点是独立的,需要先分别获取三个列表的数据,再按顺序关联合并:
组件代码
import { Component, OnInit } from '@angular/core'; import { AngularFireDatabase } from 'angularfire2/database'; @Component({ selector: 'app-bill-table', templateUrl: './bill-table.component.html' }) export class BillTableComponent implements OnInit { billToList: Array<{key: string, value: string}> = []; emailIdList: Array<{key: string, value: string}> = []; poNumberList: Array<{key: string, value: string}> = []; combinedData: Array<{billTo: string, emailId: string, poNumber: string}> = []; constructor(private db: AngularFireDatabase) {} ngOnInit(): void { // 获取Bill To数据(包含密钥) this.db.list('/EDI855/Bill To').snapshotChanges().subscribe(items => { this.billToList = items.map(item => ({ key: item.key, value: item.payload.val() as string })); this.mergeData(); }); // 获取Email Id数据 this.db.list('/EDI855/Email Id').snapshotChanges().subscribe(items => { this.emailIdList = items.map(item => ({ key: item.key, value: item.payload.val() as string })); this.mergeData(); }); // 获取Po Number数据 this.db.list('/EDI855/Po Number').snapshotChanges().subscribe(items => { this.poNumberList = items.map(item => ({ key: item.key, value: item.payload.val() as string })); this.mergeData(); }); } // 合并三个列表的数据(假设三个列表的条目顺序对应) private mergeData(): void { if (this.billToList.length && this.emailIdList.length && this.poNumberList.length) { this.combinedData = this.billToList.map((billTo, index) => ({ billTo: billTo.value, emailId: this.emailIdList[index].value, poNumber: this.poNumberList[index].value })); } } }
模板代码(HTML)
<table border="1"> <thead> <tr> <th>Bill To</th> <th>Email Id</th> <th>Po Number</th> </tr> </thead> <tbody> <!-- 用*ngFor遍历合并后的数据 --> <tr *ngFor="let item of combinedData"> <td>{{ item.billTo }}</td> <td>{{ item.emailId }}</td> <td>{{ item.poNumber }}</td> </tr> </tbody> </table>
方案2:基于优化后的 data structure(推荐)
调整结构后,获取数据和填充表格的逻辑会简单很多,还能避免数据关联出错的问题:
组件代码
import { Component, OnInit } from '@angular/core'; import { AngularFireDatabase } from 'angularfire2/database'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Component({ selector: 'app-bill-table', templateUrl: './bill-table.component.html' }) export class BillTableComponent implements OnInit { // 用Observable存储数据,配合async管道自动处理异步 orders$: Observable<Array<{key: string, billTo: string, emailId: string, poNumber: string}>>; constructor(private db: AngularFireDatabase) {} ngOnInit(): void { this.orders$ = this.db.list('/EDI855').snapshotChanges().pipe( map(items => items.map(item => ({ key: item.key, ...item.payload.val() as {billTo: string, emailId: string, poNumber: string} }))) ); // 这里console.log能看到数据,是因为Observable订阅后才会触发,而async管道会自动处理 this.orders$.subscribe(orders => console.log('订单数据:', orders)); } }
模板代码(HTML)
<table border="1"> <thead> <tr> <th>Bill To</th> <th>Email Id</th> <th>Po Number</th> </tr> </thead> <tbody> <!-- 用async管道直接订阅Observable,数据返回后自动渲染 --> <tr *ngFor="let order of orders$ | async"> <td>{{ order.billTo }}</td> <td>{{ order.emailId }}</td> <td>{{ order.poNumber }}</td> </tr> </tbody> </table>
为什么之前表格不显示?
最常见的原因是:
- 数据是异步获取的,模板渲染时数据还未返回,导致
*ngFor遍历空数组 - 模板绑定的变量名和组件中的变量名不一致
- 没有正确处理Firebase返回的快照数据(比如只取了
valueChanges()而没保留密钥,或者没正确解析数据结构)
用async管道是最省心的方式,它会自动等待数据返回后再渲染表格,避免异步时序问题。
内容的提问来源于stack exchange,提问作者Prajan
相关产品推荐
相关产品推荐

