Ionic3中AngularFire与Firebase的食谱关联数据填充实现问询
当然可以实现这个需求!结合你当前使用的AngularFire ^4.0.0-rc0、Firebase 3.9.0和Ionic3,我们可以通过嵌套Observable的方式完成数据关联填充,完美达成你想要的最终数据结构。下面是具体的实现思路和代码示例:
实现方案:关联Firebase集合填充配料详情
1. 封装数据服务
首先创建一个Angular服务来封装Firebase的数据操作,这样可以在组件中复用逻辑:
import { Injectable } from '@angular/core'; import { AngularFireDatabase } from 'angularfire2/database'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/observable/forkJoin'; import 'rxjs/add/operator/mergeAll'; @Injectable() export class RecipeService { constructor(private db: AngularFireDatabase) {} // 获取单个食谱并填充配料详情 getRecipeWithIngredients(recipeId: string): Observable<any> { return this.db.object(`/recipes/${recipeId}`).map(recipe => { // 提取当前食谱关联的所有配料ID const ingredientIds = Object.keys(recipe.ingredients); // 为每个配料ID创建获取详情的Observable const ingredientObservables = ingredientIds.map(id => this.db.object(`/ingredients/${id}`).valueChanges() ); // 合并所有Observable,等待所有配料数据返回后处理 return Observable.forkJoin(ingredientObservables).map(ingredients => { // 将配料详情映射回原ID对应的结构 const filledIngredients = {}; ingredientIds.forEach((id, index) => { filledIngredients[id] = ingredients[index]; }); // 返回填充完成的食谱对象 return { ...recipe, ingredients: filledIngredients }; }); }).mergeAll(); // 展开嵌套的Observable,方便组件直接订阅 } // 获取所有食谱并批量填充配料详情 getAllRecipesWithIngredients(): Observable<any[]> { return this.db.list('/recipes').snapshotChanges().map(actions => { return actions.map(action => { const recipe = { key: action.key, ...action.payload.val() }; const ingredientIds = Object.keys(recipe.ingredients); const ingredientObservables = ingredientIds.map(id => this.db.object(`/ingredients/${id}`).valueChanges() ); return Observable.forkJoin(ingredientObservables).map(ingredients => { const filledIngredients = {}; ingredientIds.forEach((id, index) => { filledIngredients[id] = ingredients[index]; }); return { ...recipe, ingredients: filledIngredients }; }); }); }).mergeAll(); } }
2. 在Ionic组件中调用服务
在你的页面组件中注入服务,获取填充好的数据:
import { Component } from '@angular/core'; import { RecipeService } from '../services/recipe.service'; import { Observable } from 'rxjs/Observable'; @Component({ selector: 'page-recipes', templateUrl: 'recipes.html' }) export class RecipesPage { recipes$: Observable<any[]>; constructor(private recipeService: RecipeService) { // 初始化时获取所有带配料详情的食谱 this.recipes$ = this.recipeService.getAllRecipesWithIngredients(); } // 单独获取某一个食谱的示例方法 loadSingleRecipe(recipeId: string) { this.recipeService.getRecipeWithIngredients(recipeId).subscribe(recipe => { console.log('填充完成的食谱:', recipe); // 这里可以处理单个食谱的展示逻辑 }); } }
3. 在模板中展示数据
使用Ionic的模板语法结合async管道,直接订阅并展示填充后的数据:
<ion-header> <ion-navbar> <ion-title>我的食谱</ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-item *ngFor="let recipe of recipes$ | async"> <h2>{{ recipe.name }}</h2> <!-- 这里假设你的食谱有name字段,可根据实际结构调整 --> <ion-list inset> <ion-item *ngFor="let ingredient of recipe.ingredients | keyvalue"> <p>{{ ingredient.value.text }} - {{ ingredient.value.quantity }}</p> </ion-item> </ion-list> </ion-item> </ion-list> </ion-content>
关键细节说明
forkJoin的作用:它会等待所有配料的请求都完成后,一次性返回所有配料的详情数组,刚好和我们提取的配料ID顺序对应,方便映射回原结构。mergeAll()的必要性:因为我们的方法返回的是嵌套的Observable,需要用它把嵌套结构展开成单层Observable,让组件可以直接订阅使用。- 性能提示:如果你的数据量较大,可以考虑添加缓存逻辑或者按需加载配料,但对于常规规模的食谱数据,这个方案完全够用。
内容的提问来源于stack exchange,提问作者Alberto
相关产品推荐
相关产品推荐

