Firebase Angular2 - how to query and render lists without too much overhead

前端 未结 1 1193
失恋的感觉
失恋的感觉 2021-01-19 15:25

In my application I have the following firebase posts structure:

posts: {
    text: \"..\"
    meta: {..}
    user: {
        id: \"user1\",
        username         


        
相关标签:
1条回答
  • 2021-01-19 16:11

    When looking into this question, I discovered an issue with the 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.

    A fix has been merged and will be included in the next release of AngularFire2 (that is, the release that follows 2.0.0-beta.7) - which should be soon.

    With the fix, if Angular's OnPush change detection is used, AngularFire2's FirebaseListObservable is very fast and efficient regarding DOM updates.

    I usually split the components into container and presentational components, with the container component holding the observable and with the presentational component using OnPush change detection.

    The container component would look something like this:

    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
          }
        });
      }
    }
    

    And the presentational component would look something like this:

    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[];
    }
    

    With this arrangement of components, Angular's 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.

    Another tip: a 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);
    
    0 讨论(0)
提交回复
热议问题