情况:我正在使用 FirebaseObjectObservable 来填充我的 Ionic 2 (rc0) 模板。 模板代码:
<ion-card-content>
<p>{{(course | async)?.description}}</p>
<br>
<h2>Learning Objectives</h2>
<ul>
<li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
</ul>
<h2>Takeaway</h2>
<ul>
<li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
</ul>
</ion-card-content>
TS代码:
this.course = this.af.database.object('/bbwLocations/courses/' + courseId);
this.course 是一个 Firebase 对象 Observable。一切正常!但是每当我进入模板时,就会出现空白无数据的闪光。然后所有的数据都跳出来了!非常不友好。所以我想使用某种预加载策略。但是由于这里没有 TS 逻辑。一切都在模板级别使用异步管道进行控制。在这种情况下我将如何添加负载?
也许有点晚了,但万一有人想知道如何管理这个…… 使用模板怎么样?
例如,您可以使用类似的东西:
<ion-card-content *ngIf='(course$ | async) as course; else loading'>
<p>{{course.description}}</p>
<br>
<h2>Learning Objectives</h2>
<ul>
<li *ngFor = "let objective of course.objectives">
{{objective.text}}</li>
</ul>
<h2>Takeaway</h2>
<ul>
<li *ngFor = "let takeaway of course.takeaways">
{{takeaway.text}}</li>
</ul>
</ion-card-content>
<ng-template #loading>
Loading stuff...
</ng-template>
所以你的离子卡内容将被隐藏,显示#template,直到加载异步管道。
你可以这样做:
<style>
pre {
color: orange;
// or whatever you want
}
</style>
<ion-card-content>
<p>{{(course | async)?.description}}</p>
<br>
<h2>Learning Objectives</h2>
<pre *ngIf="!(course | async)">loading objectives...</pre>
<ul>
<li *ngFor = "let objective of (course | async)?.objectives">{{objective.text}}</li>
</ul>
<h2>Takeaway</h2>
<pre *ngIf="!(course | async)">loading takeaways...</pre>
<ul>
<li *ngFor = "let takeaway of (course | async)?.takeaways">{{takeaway.text}}</li>
</ul>
</ion-card-content>
假设我们有一个可观察的meals$。我们需要在可观察对象被解析(即获取数据)时显示加载器。 下面是解决方案。
<div *ngIf="meal$ | async as meal; else loading;" >
//use the meal variable to show some data
</div>
<ng-template #loading>
//Show your loader here
</ng-template>
使用
ngIf="course$|async";else loading
的问题在于,当可观察值解析为像 0 or false
这样的虚假值时,我们会卡在加载程序屏幕上。
为了绕过这个问题,你可以考虑使用更健壮的自定义管道
第一步: 创建一个
loading.pipe.ts
文件
import { Pipe, PipeTransform } from "@angular/core"
import { Observable, isObservable, of } from "rxjs"
import { map, startWith, catchError } from "rxjs/operators"
type LoaderResponse = {
loading: boolean
value?: any
error?: any
}
@Pipe({
name: "loading",
})
export class LoadingPipe implements PipeTransform {
transform(val: Observable<any>): Observable<LoaderResponse> {
return isObservable(val)
? val.pipe(
map((value: any) => ({ loading: false, value })),
startWith({ loading: true }),
catchError((error) => of({ loading: false, error }))
)
: val
}
}
第 2 步:在
*.module.ts
文件的声明数组中注册管道
import { LoadingPipe } from "./loading.pipe"
@NgModule({
declarations: [LoadingPipe,…],
imports: [...],
exports: [...],
})
export class SharedComponentsModule {}
第三步:组件文件中的用法
<ng-container *ngIf="course$ | loading | async as course">
<div *ngIf="course?.value">
display my resolved values...
</div>
<div *ngIf="course?.error">
Error!
</div>
<div *ngIf="course?.loading">
my loader component...
</div>
</ng-container>