Firebase Angular2 - 如何在没有太多开销的情况下查询和渲染列表

2023-12-11

在我的应用程序中,我有以下 firebase posts 结构:

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

我正在使用 AngularFire2。 因此,为了获取特定用户发布的所有帖子,我运行以下查询:

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,所以我可能仍然存在一些误解。


当我研究这个问题时,我发现an issueFirebaseListObservable执行时preserveSnapshot was false- 默认行为。每次可观察对象发出一组展开的快照时,数组元素都是不同的实例 - 即使元素本身没有改变。这导致变更检测的效率大大降低。

A 修复已合并并将包含在 AngularFire2 的下一个版本中(即随后的版本)2.0.0-beta.7) - 哪个应该很快.

修复后,如果 Angular 的OnPush使用变化检测,AngularFire2的FirebaseListObservable对于 DOM 更新来说非常快速和高效。

我通常将组件分为容器和展示组件,容器组件保存可观察的内容,展示组件使用OnPush变化检测。

容器组件看起来像这样:

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

通过这种组件排列,Angular 的OnPush更改检测将确保只有实际更改的元素才会影响 DOM 更新。因此,即使很长,滚动列表也将高效且快速。

另一个提示:FirebaseListObserable当基础数据发生变化时,使用限制查询有时会发出两个值。例如,当一个新项目添加到数据库中时,会生成一个查询最近 10 个项目的列表(使用limitToLast: 10)将发出一个删除了最近的项目的数组,然后立即发出另一个添加了最近的项目的数组。如果您不想发出这两个数组中的第一个,可以使用auditTime操作员:

import "rxjs/add/operator/auditTime";

this.items = angularFire.database.list("some/fast-changing/data", {
  query: {
    limitToLast: 10
  }
})
.auditTime(0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Firebase Angular2 - 如何在没有太多开销的情况下查询和渲染列表 的相关文章

随机推荐

  • 需要帮助理解循环

    好吧 我想做的事情看起来相当简单 但它并没有按照我想要的方式工作 我知道我只是没有得到什么 本质上我正在尝试读取控制台输入 并将其分配给一个变量 然后我想检查该变量以查看它是否是有效数字 如果不是 我想告诉用户它是无效的 并重新开始循环 直
  • 变体双亚型超过最大值

    当我查看 变体数据类型 文档时 它说具有 double 子类型的变体可以支持最大 1 79769313486232E308 15 位数字 的正值 并且 当包含货币 小数和双精度值的变体变量超出其各自的范围时 会发生错误 但是 当我运行以下代
  • 如何将带有日期和时间 AM/PM 的字符串转换为 24 小时 mysql 时间戳格式

    我正在尝试从具有以下内容的字符串将日期和时间插入 mysql 日期时间字段日 月 年 时 分 秒 上午 下午 format 20 10 2014 05 39 PM 20 10 2014 05 39 AM 我知道 MYSQL 时间戳格式是 y
  • 针对 Access 数据库的 pyodbc 查询出现“可选功能未实现”错误

    对于任何可以提供帮助的人 提前表示感谢 我正在运行 64 位 Windows 10 64 位 Office 和 64 位 python 3 7 2 使用 pyodbc 我尝试执行如下所示的 Select 语句 SELECT FROM Eco
  • Flutter中如何动态生成多个Dropdown?

    我有 Java 背景 对 Flutter 很陌生 我陷入了需要动态创建多个下拉列表的场景 例如 有一项披萨优惠提供 2 个大披萨 2 个小披萨和 1 份饮料 因此 每当顾客选择任何披萨时 他 她必须选择一种口味 如果有 2 个大披萨 我需要
  • Chart.js v2:甜甜圈内甜甜圈之间的空间

    我正在使用 Chart js v2 5 0 我把甜甜圈放在甜甜圈里面 我想要两个甜甜圈之间的距离 A 变大而不影响同一甜甜圈内切片之间的距离 B 请看下图 目前我正在使用该房产边框宽度 然而 这也会影响宽度B 请看下面的代码 options
  • 为什么 akka 需要不可变消息

    或者换句话说 可变消息是否有正确的用途 我面临的用例是我想要处理基本上属于类型的对象 Map
  • SimpleHttpOperator Airflow,数据模板化

    我正在尝试正确渲染data里面一个SimpleHttpOperator在 Airflow 中 并通过我发送的配置dag run result SimpleHttpOperator task id schema detector http c
  • `%in%` 和 `==` 有什么区别?

    df lt structure list x 1 10 time c 0 5 0 5 1 2 3 0 5 0 5 1 2 3 Names c x time row names c NA 10L class data frame df df
  • 关于Struts2中的Action映射 - 没有映射Action

    我正在尝试运行我的 struts 应用程序 但收到错误操作未映射我已经看到名称空间是正确的 但仍然收到错误 struts xml
  • 响应式 2 列 CSS 布局,包括固定宽度的侧边栏?

    在任何地方都找不到这个问题的解决方案 我猜这一定是一个非常常见的问题 我正在创建一个带有侧边栏的响应式设计 其中侧边栏需要具有 200px 的固定宽度 并且高度未知 我怎样才能使主要内容区域占据所有剩余宽度 而不会出现任何异常行为 我最接近
  • 如果 scalatest 中的 FunSpec 的 afterEach 测试失败,如何确定

    在使用 FunSpec 的 scalatest 中 我有一些在 afterEach 中触发的代码 我想仅在测试失败时执行一些代码来获取屏幕截图 我所看到的几乎所有内容都试图通过将断言放入 try 块中来解决这个问题 这看起来很糟糕 Test
  • 如何等待回调函数返回?

    我正在使用phonegap 制作一个android 应用程序 我正在使用phonegap 的Storage api 来查询数据库 这是我的代码 function directPath src dest var db window openD
  • 自动调整文本输入框html大小

    我创建了一个输入 键入文本 框并使其自动调整大小非常简单 但是 有一些我似乎无法修复的故障 当我开始打字时 盒子缩小了一点 当我按退格键 或方向箭头 时 该框首先展开 然后在我继续键入时缩小 这是我的代码 function Expander
  • 反转生成的 vtable 函数顺序(具有相同名称的函数)

    如果使用 Visual Studio 2019 我使用两个具有相同名称但不同参数的虚拟方法来编译此 C 代码 struct MyStruct virtual void foo float 0 virtual void foo int 0 c
  • VBA中字符串的串联和最大长度,访问

    我在 access vba 中的字符串方面遇到了严重的问题 问题是 access 有时 将字符串的长度限制为大约 255 个字符 但是 根据字符串的构建方式 它可能会增长到超过 255 个字符 有一个工作代码的示例 Dim strReq a
  • 将父鼠标事件应用于子元素

    我正在制作小型 Windows 窗体应用程序 我里面有 PictureBox 父 和 Label 子 父元素的鼠标事件工作正常 但子元素生成的鼠标事件不会反映在父元素上 光标也会变回默认值 箭头 是否有可能pass由子控件生成的事件 例如M
  • 条件 SQL 计数

    创建计算表中数据出现次数的列的最佳方法是什么 表格需要按一列分组 我的数据库是 PostgreSQL 我见过 SELECT sum CASE WHEN question1 0 THEN 1 ELSE 0 END AS ZERO sum CA
  • Python 标准库,信号 :: AttributeError:模块“信号”没有属性“SIGALRM”

    我正在尝试设置函数超时 但是没有成功 我运行示例代码https docs python org 3 library signal html highlight signal 20sigalrm example 但是 我得到Attribute
  • Firebase Angular2 - 如何在没有太多开销的情况下查询和渲染列表

    在我的应用程序中 我有以下 firebase posts 结构 posts text meta user id user1 username 我正在使用 AngularFire2 因此 为了获取特定用户发布的所有帖子 我运行以下查询 thi