在模板中使用带有异步管道的 Observable 时显示加载
Posted
技术标签:
【中文标题】在模板中使用带有异步管道的 Observable 时显示加载【英文标题】:Display loading while using Observable with Async pipe in template 【发布时间】:2017-02-12 23:41:30 【问题描述】:情况:我正在使用 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 逻辑。一切都通过异步管道在模板级别进行控制。在这种情况下我将如何添加加载?
【问题讨论】:
路由解析器是处理视图先决条件的便捷方式。 路由器解析器是什么意思?我在 Ionic 2 RC0 中。我相信没有路由器。 我不使用 Ionic,但至少 A2 路由器可以实现这一点angular.io/docs/ts/latest/guide/router.html#!#resolve-guard 我不知道 I2 与 A2 路由器的性能有多好。无论如何,处理它的最佳方法是在组件初始化之前解决依赖关系(例如,如果您将其用于导航,则在调用nav.push
之前)。
【参考方案1】:
你可以这样做:
<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>
【讨论】:
这行得通。但是如果我想要退出动画,比如当 ngIf 变为 false 时淡出加载器。我将无法做到这一点。另外,是否可以利用可观察对象并为此使用 Ionic Loader 组件? 如果你想使用 ngIf 我相信Animations
是要走的路。您可以使用 ngClass 代替 ngIf 并使用 CSS 制作动画/过渡。 transition: 1s opacity 0.5s linear
,诸如此类……
您能否更新您的解决方案并举例说明如何轻松使用动画来淡出 pre 元素?谢谢!
但这会产生很多不必要的请求... :(
如果它重复了你的请求:你让观察者可以访问一个冷的 observable。您应该使用share()
或类似设置course
作为热可观察对象。 this.course = this.httpClient.get('whatever').pipe(shareReplay(1))
。这将存储最新的结果,因此如果您有多个订阅者:他们可以观察结果的重播,而不是发起新的 HTTP 请求。【参考方案2】:
也许有点晚了,但万一其他人想知道如何管理这个...... 使用模板怎么样?
你可以使用类似的东西:
<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>
所以你的 ion-card-content 将被隐藏,显示 #template,直到异步管道被加载。
【讨论】:
【参考方案3】:假设我们有一个可观察的 meals$。当 observable 被解析(即获取数据)时,我们需要显示加载器。 下面是解决方案。
<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>
【讨论】:
以上是关于在模板中使用带有异步管道的 Observable 时显示加载的主要内容,如果未能解决你的问题,请参考以下文章
使用异步管道显示从应用程序状态检索到的 Observable 数据