资讯动态

AngularFire Realtime Database 列表数据实战指南:AngularFireList 的读取、写入与删除全解析

发布时间:2026/9/27 11:12:16 来源:尧图企业网站定制
后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载本篇指南以 AngularFire 仓库中 site/src/rtdb/lists.md 文档为主体结合 src/compat/database 目录下的真实源码与测试用例系统讲解如何使用AngularFireList以列表形式实时同步 Firebase Realtime Database 数据。读完本文你将掌握AngularFireDatabase的注入方式、valueChanges()/snapshotChanges()/stateChanges()/auditTrail()四种流式 API 的适用场景、事件过滤机制以及push()/set()/update()/remove()等增删改操作的完整用法并能在自己的 Angular 组件中直接落地一个可运行的列表 CRUD 示例。AngularFire 使用AngularFireList服务将 Realtime Database 中的数据以列表形式同步。AngularFireList并非独立创建而是通过AngularFireDatabase服务产生的。下面的指南将演示如何以列表形式检索、保存和删除数据。注入AngularFireDatabase服务前提请确保你已经为应用完成了 AngularFire 的引导bootstrap配置详见 安装与配置指南。AngularFireDatabase是一个服务可以通过 Angular 组件或Injectable()服务的构造函数注入。在上一节对象数据指南中我们修改了/src/app/app.component.ts以对象形式检索数据本节从干净状态开始。将你的/src/app/app.component.ts替换为以下内容import { Component } from angular/core; import { AngularFireDatabase } from angular/fire/database; Component({ selector: app-root, templateUrl: app.component.html, styleUrls: [app.component.css] }) export class AppComponent { constructor(db: AngularFireDatabase) { } }在本节中我们将继续修改/src/app/app.component.ts以列表形式检索数据但在此之前先来看一下如何绑定到一个列表。创建列表绑定数据通过AngularFireDatabase服务检索。该服务是泛型的——请提供单数类型元素类型而不是数组类型const listRef db.list(items); const shirtsRef db.listShirt(shirts);从源码看db.list()在 src/compat/database/database.ts 中的实现是先通过getRef()解析路径得到Reference若传入了可选的queryFn则对引用执行查询转换最后调用createListReferenceT()返回一个AngularFireListT实例listT(pathOrRef: PathReference, queryFn?: QueryFn): AngularFireListT { const ref inject(NgZone).runOutsideAngular(() getRef(this.database, pathOrRef)); let query: DatabaseQuery ref; if (queryFn) { query queryFn(ref); } return createListReferenceT(query, this, this.injector); }检索数据要实现实时获取列表请将列表绑定创建为组件或服务的属性然后在模板中使用async管道解包该绑定。更新/src/app/app.component.ts从angular/fire导入AngularFireList并在数据检索后遍历列表。同时注意下面把属性templateUrl改成了内联templateimport { Component } from angular/core; import { AngularFireDatabase } from angular/fire/database; import { Observable } from rxjs; Component({ selector: app-root, template: ul li *ngForlet item of items | async {{ item | json }} /li /ul , }) export class AppComponent { items: Observableany[]; constructor(db: AngularFireDatabase) { this.items db.list(items).valueChanges(); } }AngularFireList的完整接口定义在 src/compat/database/interfaces.ts它包含query引用、四个流式方法valueChanges/snapshotChanges/stateChanges/auditTrail以及四个写操作update/set/push/remove。AngularFireAction—— 基于 Action 的 APIAngularFire 提供了一系列方法将数据以Redux 兼容的 action形式流式返回。在与 Animations、ngrx、ReactiveForms 等库配合使用时这能带来额外的能力如利用type属性驱动 reducer、表单状态与动画状态。valueChanges()是什么返回一个 Observable输出为同步的 JSON 对象数组。所有 Snapshot 元数据被剥离该方法只提供数据本身。为什么用它当你只需要一个数据列表时。结果数组不带任何快照元数据渲染到视图非常简单。什么时候不用它当你需要比数组更复杂的数据结构或者需要每个快照的key来做数据操作时。此方法隐含的假设是你要么已经保存了快照数据的key要么采用只读方式使用。一个值得注意的细节在 src/compat/database/list/create-reference.ts 的实现中valueChanges()还支持通过第二个参数options.idField把每条记录的key合并进返回对象便于在只拿数据的同时保留主键valueChangesK extends string(events?: ChildEvent[], options?: {idField: K}): Observable(T Recordstring, string)[] { const snapshotChanges$ snapshotChangesT(query, events, outsideAngularScheduler); return snapshotChanges$.pipe( map(actions actions.map(a { if (options?.idField) { return { ...a.payload.val() as T, ...{ [options.idField]: a.key } }; } else { return a.payload.val() as T Recordstring, string } })), pendingUntilEvent(injector) ); }snapshotChanges()是什么返回一个 Observable输出为同步的AngularFireActionDatabaseSnapshot[]数组。为什么用它当你需要列表数据、同时想保留元数据时。元数据提供了底层的DatabaseReference和快照key。保留快照的key使得调用数据操作方法更简单。由于每个AngularFireAction都带有type属性此方法在与 ngrx、forms、animations 等 Angular 集成时拥有更强的能力——type属性对 ngrx reducer、表单状态和动画状态都非常有用。什么时候不用它当你需要比数组更复杂的数据结构或需要按发生顺序逐个处理变更时。此数组与 Firebase Database 的远端和本地变更保持同步数组形态。AngularFireAction的结构定义在 src/compat/database/interfaces.tsexport interface ActionT { type: ListenEvent; payload: T; } export interface AngularFireActionT extends ActionT { prevKey: string | null | undefined; key: string | null; }每个 action 除了type和payload内含DatabaseSnapshot外还携带prevKey与key这正是构建同步数组视图的关键素材。底层实现listChanges()位于 src/compat/database/list/changes.ts先once读取一次value作为初始快照再对指定事件on监听增量变更最后通过scan(buildView, [])累积出始终有序、去重的数组视图并用distinctUntilChanged()避免重复发射。stateChanges()是什么返回一个 Observable每次发射最近一次变更对应的单个AngularFireAction。为什么用它前面两个方法是在每个子事件发生时返回一个AngularFireAction数组而stateChanges()按事件发生的顺序逐个发射而不是同步查询顺序。这非常适合 ngrx 集成——你可以在自己的 reducer 方法中构建自定义数据结构。什么时候不用它当你只需要一个数据列表时。这是AngularFireDatabase的更高级用法。从 src/compat/database/list/state-changes.ts 可以看出它的实现本质将每个监听事件用fromRef转成流再通过 RxJSmerge合并因此每个变更独立发射不做数组累积export function stateChangesT(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike) { events validateEventsArray(events); const childEvent$ events.map(event fromRefT(query, event, on, scheduler)); return merge(...childEvent$); }auditTrail()是什么返回一个 Observable输出为随时间累积的AngularFireAction[]。与stateChanges()类似但它把事件的完整轨迹保留为数组。为什么用它它像stateChanges()但不具有瞬时性每发生一次变更就把该变更收集进数组。这对于需要重放整个应用状态的 ngrx 集成非常有用同时也是一个极好的调试工具——你可以直接写db.list(items).auditTrail().subscribe(console.log)在控制台里观察每个事件的发生过程。什么时候不用它当你只需要一个数据列表时。这是AngularFireDatabase的更高级用法。auditTrail()的实现位于 src/compat/database/list/audit-trail.ts基于stateChanges()用scan把每个 action 追加进数组再通过一次value快照定位最后加载的 key只有当数据集的最后一个 key 已被子事件加载完毕后才开始发射从而保证轨迹数组是完整的。限制事件Limiting eventsRealtime Database 共有四种子事件child_added、child_changed、child_removed和child_moved。默认情况下上述每个流式方法都会监听全部四种事件。但如果你的站点只关心其中一种可以通过每个方法的第一个参数指定要监听的事件this.itemsRef db.list(items); this.itemsRef.snapshotChanges([child_added]) .subscribe(actions { actions.forEach(action { console.log(action.type); console.log(action.key); console.log(action.payload.val()); }); });从 src/compat/database/list/utils.ts 的validateEventsArray()可以看到默认行为的确切来源当参数为空或长度为零时会自动补全为全部四种ChildEventexport function validateEventsArray(events?: any[]) { if (isNil(events) || events.length 0) { events [child_added, child_removed, child_changed, child_moved]; } return events; }而ChildEvent类型定义在 src/compat/database/interfaces.tschild_added | child_removed | child_changed | child_moved。仓库中的测试 src/compat/database/list/snapshot-changes.spec.ts 也验证了默认监听所有事件以及只监听child_added等行为。API 概览下表列出了AngularFireList上一些常用的方法除push外实际还包括set方法说明push(value: T)在列表上创建一条新记录使用 Realtime Database 的 push-ids 生成唯一键。set(keyRefOrSnap, value: T)用新值整体替换指定位置的已有数据。接受 key、database reference 或 unwrapped snapshot。update(keyRefOrSnap: string, value: T)更新数组中的现有项。接受 key、database reference 或 unwrapped snapshotFirebase | AFUnwrappedSnapshot。remove(key: string?)按 key 删除数据项。若不传参数则删除整个列表。这三个写操作在源码中均通过checkOperationCases()src/compat/database/utils.ts统一分派参数是字符串时定位到子节点是firebase.database.Reference时直接在该引用上操作是DataSnapshot时通过snapshot.ref操作。update/set的创建逻辑见 src/compat/database/list/data-operation.tsremove的逻辑见 src/compat/database/list/remove.ts无参数时直接ref.remove()删除整棵子树。返回 Promise上表中的每个数据操作方法都会返回一个 Promise。不过你很少需要用这个完成态 Promise 来指示成功——因为实时数据库会持续保持列表同步。Promise 的真正价值在于串联多个操作、捕获安全规则security rules拒绝导致的错误或用于调试。const promise db.list(items).remove(); promise .then(_ console.log(success)) .catch(err console.log(err, You do not have access!));例如上面这个例子当 Firebase 安全规则禁止当前用户删除items时.catch就能捕获到拒绝信息并给出提示。添加新数据项使用push()方法向列表添加新数据项。push()会由 Realtime Database 生成一个全局唯一的 push-id 作为新节点的 keyconst itemsRef db.list(items); itemsRef.push({ name: newName });从 src/compat/database/interfaces.ts 可见push()的返回类型是firebase.database.ThenableReference——它既是一个Reference可通过.key拿到新生成的主键又是一个可 await 的 Promise。使用set替换列表中的数据项使用set()方法更新已有数据项const itemsRef db.list(items); // 如何获取 key请参考下面的完整示例 itemsRef.set(key-of-some-data, { size: newSize });set()会用参数指定的新值整体替换数据库中的当前值。这被称为破坏性更新destructive update因为它会删除当前位置上的所有现有内容再写入新值。使用update更新列表中的数据项使用update()方法更新已有数据项const itemsRef db.list(items); // 如何获取 key请参考下面的完整示例 itemsRef.update(key-of-some-data, { size: newSize });注意update()会以参数指定的新值更新数据库中的当前值。这被称为非破坏性更新non-destructive update因为它只修改你指定的字段其余字段保持不变。这是它与set()最核心的区别update是局部修补set是整体覆盖。从列表中移除数据项使用remove()方法删除列表项位置上的数据const itemsRef db.list(items); // 如何获取 key请参考下面的完整示例 itemsRef.remove(key-of-some-data);删除整个列表如果省略remove()的key参数它会删除整个列表const itemsRef db.list(items); itemsRef.remove();下面是一个完整的删除整个列表的示例组件同时演示了完整的 CRUD 流程通过snapshotChanges()配合map把快照的key并入数据对象从而让模板中的Update / Delete / Add / Delete All按钮都能拿到目标 keyimport { Component } from angular/core; import { AngularFireDatabase, AngularFireList } from angular/fire/database; import { Observable } from rxjs; import { map } from rxjs/operators; Component({ selector: app-root, template: ul li *ngForlet item of items | async input typetext #updatetext [value]item.text / button (click)updateItem(item.key, updatetext.value)Update/button button (click)deleteItem(item.key)Delete/button /li /ul input typetext #newitem / button (click)addItem(newitem.value)Add/button button (click)deleteEverything()Delete All/button , }) export class AppComponent { itemsRef: AngularFireListany; items: Observableany[]; constructor(db: AngularFireDatabase) { this.itemsRef db.list(messages); // Use snapshotChanges().map() to store the key this.items this.itemsRef.snapshotChanges().pipe( map(changes changes.map(c ({ key: c.payload.key, ...c.payload.val() })) ) ); } addItem(newName: string) { this.itemsRef.push({ text: newName }); } updateItem(key: string, newText: string) { this.itemsRef.update(key, { text: newText }); } deleteItem(key: string) { this.itemsRef.remove(key); } deleteEverything() { this.itemsRef.remove(); } }结合实战现代 tree-shakable API 的对照上文围绕AngularFireList服务compat 风格 API展开这也是 site/src/rtdb/lists.md 文档所采用的主体形式。需要说明的是当前仓库同时提供了新一代 tree-shakable API见 src/database/public_api.ts 与 docs/database.md在app.config.ts中通过provideDatabase(() getDatabase())提供数据库实例然后直接使用listVal(query)、stateChanges(query)、auditTrail(query)、list(query)等 RxJS 辅助函数。其中listVal()相当于列表场景下的valueChanges()同样可选keyField携带主键list()相当于snapshotChanges()的函数式版本两者都支持通过events选项过滤子事件类型。仓库示例 sample/src/app/database/database.component.ts 即采用了这套新 API。无论选择哪套 API本文讲解的四种流式方法语义、四种ChildEvent事件、以及push/set/update/remove的增删改语义都是相通的。下一步掌握了列表的读取与写入后接下来可以学习列表查询对列表进行排序与过滤并结合 RxJSswitchMap实现动态查询详见 Querying lists列表查询指南。查询时需注意一次查询只能使用一种排序方法且limitToFirst与limitToLast不能同时使用。赞分享后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载相关推荐AngularFire 兼容层 Realtime Database 对象绑定实战用 AngularFireObject 实时读写与同步对象数据AngularFire 兼容层 Realtime Database 对象绑定实战用 AngularFireObject 实时读写与同步对象数据 本文是 Ang后端AngularFirecompatRealtime Database 列表查询完全指南从基础 Query 到 RxJS 动态查询AngularFirecompatRealtime Database 列表查询完全指南从基础 Query 到 RxJS 动态查询 本文基于 Angular后端pypdf PDF 元数据完全指南Document Info 与 XMP 的读取、写入、更新与删除pypdf PDF 元数据完全指南Document Info 与 XMP 的读取、写入、更新与删除 本文系统讲解 pypdf 中处理 PDF 元数据的全部能力后端上一篇霞鹜文楷屏幕阅读版终极免费开源字体指南下一篇workerd 测试框架 .wd-test 文件格式完全指南从配置编写到 Bazel 集成创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑