Firebase Angular2 - 如何查询和呈现列表,没有太多的开销 [英] Firebase Angular2 - how to query and render lists without too much overhead
问题描述
在我的应用程序中,我有以下firebase文章结构:
文章:{
text:..
meta:{..}
user:{
id:user1,
username:..
}
}
我正在使用angularfire2。
因此,要获取特定用户发布的所有帖子,我运行以下查询:
$ p $ this.userPosts $ = this.af.database.list('/ posts',{
query:{
orderByChild:'user / id',
equalTo:userId
}
} ).map((posts)=> {
return posts.map(post => Post.unpack(post));
})。publishReplay(1).refCount();
我听说这不是很有效率,因为每次改变的时候),整个列表被重新载入,并因此被重新渲染。而且由于我在我的应用程序中有喜欢和不喜欢,这往往会发生。基本上每次有人喜欢一个职位,整个列表是重新加载每个用户,如果我没有错。
我知道有一种方法来维护本地复制列表,同时听取firebase事件:child_added,child_removed和child_changed。
但是,如果我将这些事件附加到查询列表中,那么每当原始帖子列表中的内容整体发生变化时,它们就会触发。
,我正在考虑采取什么方法。如果这是唯一不错的选择,我可能会将帖子数据复制到firebase中的user_posts列表中。然而,用这种方法,我觉得查询几乎是无用的,我失去了灵活性。我刚开始使用firebase大约一个星期前,所以我可能仍然有一些误解。
<当看到这个问题时,我发现问题与<$ c $当$ preserveSnapshot
为 false
时,FirebaseListObservable 实现 - 默认行为。每当observable发出一个打开的快照数组时,数组元素就是不同的实例 - 即使元素本身没有改变。这导致了检测效率低得多。
A fix已被合并,并将被包含在下一个版本的AngularFire2中(也就是后面的版本 2.0.0-beta.7
) - 应该很快。
通过修复,如果使用Angular的 OnPush
变更检测,AngularFire2的 FirebaseListObservable
是非常快速和有效的DOM更新。
我通常将组件分成,其中容器组件包含可观察的元素,并且呈现组件使用 T他的容器组件看起来像这样: 这个表示性的组件看起来像这样: / b> 通过这种安排,Angular的 In my application I have the following firebase posts structure: I'm using angularfire2.
So, to get all posts posted by specific user, I run the following query: I've heard that it's not very efficient, since every time something changes (even in a single post), the whole list is reloaded and, thus, re-rendered. And since I have likes and dislikes in my app, this is gonna happen pretty often. Basically every time someone likes a post, the whole list is reloaded for every user, if I'm not mistaken. I know that there is a way to maintain a local copy of the list while listening to firebase events: "child_added", "child_removed" and "child_changed".
However, if I attach these events to the queried list, they are going to fire each time something changes in the original posts list as a whole. So, I am thinking what approach to take here. I might duplicate posts data into "user_posts" list in firebase if it is the only good choice. However, with this approach I feel that querying becomes almost useless and I lose flexibility. I started to use firebase just about a week ago, so I might still have some misunderstandings. When looking into this question, I discovered an issue with the A fix has been merged and will be included in the next release of AngularFire2 (that is, the release that follows With the fix, if Angular's I usually split the components into container and presentational components, with the container component holding the observable and with the presentational component using The container component would look something like this: And the presentational component would look something like this: With this arrangement of components, Angular's Another tip: a
这篇关于Firebase Angular2 - 如何查询和呈现列表,没有太多的开销的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! OnPush
变化检测。
$ b
import {Component} from@ angular / core ;
从angularfire2导入{AngularFire,FirebaseListObservable};
$ b @Component({
selector:items-container,
template:`< items-component [items] =items | async>< items-component>`
})
export class ItemsContainer {
private items:FirebaseListObservable< any> ;;
构造函数(private angularFire:AngularFire){
this.items = angularFire.database.list(some / fast-changing / data,{
query:{
limitToLast:1000
}
});
从@ angular / core导入{ChangeDetectionStrategy,Component,Input};
@Component({
changeDetection:ChangeDetectionStrategy.OnPush,
selector:items-component,
template:`
< ul> $
< li * ngFor =let item of items> {{item | json}}< / li>
< / ul>
`
})
导出类ItemsComponent {
@Input()items:any [];
$ b $ p
$ b OnPush code> change detection将确保只有实际更改的元素才会影响DOM更新。因此,即使长时间,滚动列表也会高效快速。另外一个技巧:使用限制查询的
FirebaseListObserable
当底层数据发生变化时,有时会发出两个值。例如,当一个新项目被添加到数据库中时,一个查询10个最近项目(使用 limitToLast:10
)的列表将会发出一个包含最近项目的数组删除,然后立即发出另一个最近添加的项目。如果不希望这两个数组中的第一个被发射,则可以使用 auditTime
操作符:
importrxjs / add / operator / auditTime;
this.items = angularFire.database.list(some / fast-changing / data,{
query:{
limitToLast:10
}
})
.auditTime(0);
posts: {
text: ".."
meta: {..}
user: {
id: "user1",
username: ".."
}
}
this.userPosts$ = this.af.database.list('/posts', {
query: {
orderByChild: 'user/id',
equalTo: userId
}
}).map( (posts) => {
return posts.map(post => Post.unpack(post));
}).publishReplay(1).refCount();
FirebaseListObservable
implementation when preserveSnapshot
was false
- the default behaviour. Each time the observable emitted an array of unwrapped snapshots, the array elements were different instances - even if the elements themselves had not changed. And this resulted in much less efficient change detection.2.0.0-beta.7
) - which should be soon.OnPush
change detection is used, AngularFire2's FirebaseListObservable
is very fast and efficient regarding DOM updates.OnPush
change detection.import { Component } from "@angular/core";
import { AngularFire, FirebaseListObservable } from "angularfire2";
@Component({
selector: "items-container",
template: `<items-component [items]="items | async"></items-component>`
})
export class ItemsContainer {
private items: FirebaseListObservable<any>;
constructor(private angularFire: AngularFire) {
this.items = angularFire.database.list("some/fast-changing/data", {
query: {
limitToLast: 1000
}
});
}
}
import { ChangeDetectionStrategy, Component, Input } from "@angular/core";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "items-component",
template: `
<ul>
<li *ngFor="let item of items">{{ item | json }}</li>
</ul>
`
})
export class ItemsComponent {
@Input() items: any[];
}
OnPush
change detection will ensure that only the elements that have actually changed will effect DOM updates. So even long, scrolling lists will be efficient and fast.FirebaseListObserable
that uses a limit query will sometimes emit two values when the underlying data changes. For example, when a new item is added to the database, a list that queries the 10 most recent items (using limitToLast: 10
) will emit an array with the least recent item removed and will then immediately emit another with the most recent item added. If you don't want the first of those two arrays to be emitted, you can use the auditTime
operator:import "rxjs/add/operator/auditTime";
this.items = angularFire.database.list("some/fast-changing/data", {
query: {
limitToLast: 10
}
})
.auditTime(0);