Ionic/Firebase RTDB:获取对象键值用于页面导航
获取AngularFireList对象键的最佳实践
我刚好之前在Ionic+Firebase项目里遇到过完全一样的需求,给你几个靠谱的解决方案,都是适配AngularFire 5.x版本的:
方法一:在服务层合并键与数据(推荐)
valueChanges()确实只会返回纯数据,不带键值,而snapshotChanges()会给我们包含元数据的快照,其中就有我们需要的payload.key。你可以在你的数据提供者里直接处理,把键和数据合并成新对象,这样所有页面调用这个服务时都能直接拿到带键的数据:
// 你的Firebase数据服务文件 import { Injectable } from '@angular/core'; import { AngularFireDatabase, AngularFireList } from '@angular/fire/database'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class DataService { private itemsRef: AngularFireList<any>; constructor(private db: AngularFireDatabase) { this.itemsRef = db.list('your-rtdb-path'); // 替换成你的RTDB节点路径 } // 修改后的获取方法,返回带键的对象数组 getItemsWithKey(): Observable<any[]> { return this.itemsRef.snapshotChanges().pipe( map(changes => changes.map(snap => ({ key: snap.payload.key, // 提取节点键值 ...snap.payload.val() // 合并原数据 })) ) ); } }
然后在页面里使用这个方法,订阅后每个对象就自带key属性了,导航时直接传这个值:
// 页面组件 import { Component } from '@angular/core'; import { DataService } from '../services/data.service'; import { NavController } from '@ionic/angular'; @Component({ selector: 'app-home', templateUrl: 'home.page.html' }) export class HomePage { items$: Observable<any[]>; constructor( private dataService: DataService, private navCtrl: NavController ) { this.items$ = this.dataService.getItemsWithKey(); } // 跳转方法,传递键值作为参数 goToDetail(item: any) { this.navCtrl.navigateForward(['/detail-page', item.key]); } }
模板里直接用async管道渲染,点击时调用跳转方法:
<ion-list> <ion-item *ngFor="let item of items$ | async" (click)="goToDetail(item)"> {{ item.name }} <!-- 替换成你的数据字段 --> </ion-item> </ion-list>
方法二:在页面层单独处理(适合临时场景)
如果不想修改服务,也可以在页面里直接对原AngularFireList调用snapshotChanges()处理:
// 页面组件里的代码 import { Component } from '@angular/core'; import { AngularFireList } from '@angular/fire/database'; import { DataService } from '../services/data.service'; import { map } from 'rxjs/operators'; @Component({ selector: 'app-home', templateUrl: 'home.page.html' }) export class HomePage { items$: Observable<any[]>; constructor(private dataService: DataService) { // 假设你的服务原来返回的是AngularFireList const rawList: AngularFireList<any> = this.dataService.getRawItems(); this.items$ = rawList.snapshotChanges().pipe( map(changes => changes.map(snap => ({ key: snap.payload.key, ...snap.payload.val() }))) ); } }
目标页面接收参数
最后在跳转后的页面,用ActivatedRoute接收传递的键值:
// 详情页组件 import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { DataService } from '../services/data.service'; @Component({ selector: 'app-detail', templateUrl: 'detail.page.html' }) export class DetailPage { itemKey: string; constructor( private route: ActivatedRoute, private dataService: DataService ) { // 获取路由参数里的键值 this.itemKey = this.route.snapshot.paramMap.get('key'); // 用这个键值去RTDB获取对应的数据 this.dataService.getItemByKey(this.itemKey).subscribe(item => { // 处理数据 }); } }
顺便提一句,AngularFire 5.x里还有stateChanges()方法,不过snapshotChanges()已经完全满足我们获取键值的需求,而且更常用。
内容的提问来源于stack exchange,提问作者user7562030
相关产品推荐
相关产品推荐

