尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AngularFire Compat 实时数据库列表(AngularFireList)完全指南:绑定、查询与增删改操作

AngularFire Compat 实时数据库列表(AngularFireList)完全指南:绑定、查询与增删改操作 后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载AngularFire 为 Angular 应用封装了 Firebase Realtime Database 的列表数据同步能力其中AngularFireList服务用于将数据库中的一组数据以实时同步的列表形式绑定到组件与服务中。本文基于 AngularFire 当前仓库中 compat兼容版本 API 的官方指南结合 list 相关源码 与 类型定义系统讲解如何注入AngularFireDatabase、创建列表绑定、使用valueChanges()/snapshotChanges()/stateChanges()/auditTrail()四类 Action 流式 API以及push/set/update/remove等写操作的完整实战用法。兼容版本说明AngularFire 现已提供新的 tree-shakable API详见仓库根 README 开发者指南本文面向的是compat兼容版本的库。若需了解新旧 API 的迁移差异可参考 v7 升级指南。1. 概览AngularFireList是什么AngularFireList是一个用于同步 Realtime Database 列表数据的服务它不会独立创建而是统一通过AngularFireDatabase服务来获取它负责把数据库路径下的数据集合以实时同步的数组形式暴露给 Angular 组件在底层它基于 Firebase SDK 的Reference/Query与 child 级事件child_added、child_removed、child_changed、child_moved构建 Observable 流它同时提供读流式检索与写push/set/update/remove两类能力。从源码看createListReference见 src/compat/database/list/create-reference.ts把一个DatabaseQuery与AngularFireDatabase实例组合成AngularFireListT对象其暴露的方法包括update、set、push、remove、snapshotChanges、stateChanges、auditTrail、valueChanges接口定义可对照 src/compat/database/interfaces.ts。2. 注入AngularFireDatabase服务使用列表功能前需要先完成 AngularFire 的应用引导bootstrap配置参见仓库中的安装引导文档install-and-setup.md。AngularFireDatabase是一个可注入的 Angular 服务既可以在组件的构造函数中注入也可以注入到Injectable()装饰的普通服务中。在引导步骤中应用入口的app.component.ts通常已被修改为检索对象数据这一步我们先从一个干净的状态开始将其替换为仅注入AngularFireDatabase的骨架import { Component } from angular/core; import { AngularFireDatabase } from angular/fire/compat/database; Component({ selector: app-root, templateUrl: app.component.html, styleUrls: [app.component.css] }) export class AppComponent { constructor(db: AngularFireDatabase) { } }注意这里的导入路径是angular/fire/compat/database这正是 compat 版本模块的入口对应仓库中的 src/compat/database/public_api.ts。接下来我们将逐步把列表数据绑定到这个组件上。3. 创建列表绑定数据通过AngularFireDatabase服务的list()方法获取。该方法是一个泛型方法传入的是单个元素的类型而不是数组类型——AngularFireList会在内部替你管理数组。const listRef db.list(items); // 元素类型为 any const shirtsRef db.listShirt(shirts); // 元素类型为 Shirtdb.list()的第一个参数是数据库路径相对路径即可无需以/开头。从源码接口看list还支持第二个参数——查询函数QueryFn (ref: DatabaseReference) DatabaseQuery见 interfaces.ts它用于在绑定时附加orderByChild、equalTo等排序过滤条件这部分在“查询列表”指南中有专门讲解querying-lists.md。3.1 实时检索数据要获得实时同步的列表把列表绑定声明为组件或服务的属性即可。模板中配合 RxJS 的async管道解包绑定Angular 会在数据变化时自动更新视图。更新app.component.ts导入AngularFireList与Observable并通过valueChanges()获取纯数据数组同时把templateUrl改为内联templateimport { Component } from angular/core; import { AngularFireDatabase } from angular/fire/compat/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(); } }*ngForlet item of items | async会订阅items这个 Observable每当数据库中的数据发生增删改时列表都会自动刷新无需手动管理订阅与变更检测。4.AngularFireAction—— 基于 Action 的流式 APIAngularFireList提供多种方法把数据以Redux 风格的动作action流式返回。每个 action 带有type事件类型、key快照键与payload数据载荷在与 Animations、ngrx、ReactiveForms 等库配合时能发挥更大威力。AngularFireActionT接口定义可参见 src/compat/database/interfaces.ts其中type为ListenEventvalue或四种 child 事件之一并带有prevKey与key。下面逐一对比四种方法的适用场景。4.1valueChanges()是什么返回一个 Observable数据为同步后的 JSON 对象数组。所有 Snapshot 元数据被剥离只提供数据本身。为什么用它当你只需要一份数据列表时最合适。结果数组不带任何快照元数据渲染到视图上非常简单配合async管道即可。什么时候不用它当你需要比数组更复杂的数据结构或者需要每个快照的key来做数据操作时就不要用此方法。它隐含的前提是要么你已把key保存进快照数据本身要么采用“只读”方案。从源码实现看create-reference.tsvalueChanges()内部基于snapshotChanges()流做map逐个把a.payload.val()取出它还支持一个可选的options.idField参数——当传入{ idField: id }时会把每个子项的key以指定字段名合并进返回对象这在需要随数据携带key的场景下非常实用// 源码能力将 key 合并进每个数据项 this.items db.list(items).valueChanges({ idField: id });4.2snapshotChanges()是什么返回一个 Observable数据为同步后的AngularFireActionDatabaseSnapshot[]数组即SnapshotActionT[]。为什么用它当你需要列表数据、同时希望保留元数据时使用。元数据提供底层的DatabaseReference与快照key拿到快照的key后可以方便地调用update/remove等数据操作方法。此外每个 action 的type属性对 ngrx reducer、表单状态、动画状态都很有价值。什么时候不用它当需要比数组更复杂的数据结构或需要“逐条处理变更发生时”的场景。该方法返回的数组始终与 Firebase Database 的远端与本地变更保持同步。snapshotChanges()的底层由listChanges实现src/compat/database/list/changes.ts先通过fromRef(ref, value, once)读取一次完整数据集再合并各 child 事件的监听流用scan(buildView, [])增量构建视图数组最后经distinctUntilChanged()去重。buildView会根据child_added/child_removed/child_changed/child_moved四种类型分别做插入、过滤、替换与重排见 changes.ts。4.3stateChanges()是什么返回一个 Observable每次只发出最近一次变更对应的单个AngularFireAction而不是同步整个查询顺序。为什么用它上述两个方法把每个 child 事件合并成同步后的数组而stateChanges()按事件发生的先后逐个发出 action很适合 ngrx 集成——你可以在自己的 reducer 里自行构建数据结构。什么时候不用它当你只需要一份列表数据时。这是AngularFireDatabase的更高级用法。源码中stateChanges()的实现非常直白src/compat/database/list/state-changes.ts对每个监听事件调用fromRef(query, event, on)得到独立流再用 RxJSmerge(...)合并输出。4.4auditTrail()是什么返回一个 Observable按发生顺序发出AngularFireAction[]数组。与stateChanges()类似但不丢弃历史——它把每个变更累积在一个数组中。为什么用它它不像stateChanges()那样“转瞬即逝”而是把所有变更收集成数组适用于需要在 ngrx 中重放应用完整状态的集成场景同时它也是绝佳的调试工具——只需一行db.list(items).auditTrail().subscribe(console.log)就能在控制台里跟踪所有事件。什么时候不用它当你只需要一份列表数据时。同样是更高级的用法。其源码src/compat/database/list/audit-trail.ts基于stateChanges()流用scan((current, action) [...current, action], [])累积数组再通过waitForLoaded等待初始数据集的最后一个key被 child 事件加载完毕后才开始发射audit-trail.ts从而保证输出的数组是“完整”的数据集。4.5 限制监听的事件类型Realtime Database 共有四种 child 事件child_addedchild_changedchild_removedchild_moved默认情况下上述每个流式方法都会同时监听全部四种事件源码中validateEventsArray在未传参或传入空数组时会补全为四种事件见 src/compat/database/list/utils.ts。但你的业务可能只关心其中某一种此时可以在每个方法的第一个参数中指定事件列表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()); }); });四个流式方法的events参数类型均为ChildEvent[]其中ChildEvent child_added | child_removed | child_changed | child_moved见 interfaces.ts。5. 保存数据API 汇总下表汇总了AngularFireList上常用的写操作方法方法说明push(value: T)在列表上创建一条新记录使用 Realtime Database 的 push-id 作为键。update(keyRefOrSnap: string, value: T)更新数组中已存在的一项。参数接受一个 key字符串、一个数据库引用DatabaseReference或一个未解包的快照AFUnwrappedSnapshot/DataSnapshot。remove(key: string?)按 key 删除对应项若不传参数则删除整个列表。从源码看update与set都由createDataOperationMethod生成src/compat/database/list/data-operation.ts内部通过checkOperationCases区分三种入参形态字符串 keyref.child(item)operationFirebase 引用直接对DatabaseReference调用对应操作快照取快照的ref再执行对应操作。也就是说update/set的“目标项”可以用 key 字符串、Reference或DataSnapshot三种方式指定与接口中FirebaseOperation string | firebase.database.Reference | firebase.database.DataSnapshot见 interfaces.ts完全对应。5.1 方法返回 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!));例如当数据库安全规则禁止当前用户删除数据时错误会进入catch分支这正是用 Promise 捕获权限拒绝的典型场景。6. 列表写操作实战6.1 添加新项push()使用push()向列表添加新项。它会生成一个唯一的 push-id并保证多客户端并发写入时键值不冲突const itemsRef db.list(items); itemsRef.push({ name: newName });push的返回值是firebase.database.ThenableReference见 interfaces.ts如果需要新记录的 key可以通过该引用获得。6.2 替换项set()使用set()更新已存在的项。它会用参数中的新值整体替换数据库中的当前值属于破坏性更新——先删除当前位置的所有内容再写入新值const itemsRef db.list(items); // 若要获取 key可参考下文“完整示例” itemsRef.set(key-of-some-data, { size: newSize });6.3 更新项update()使用update()更新已存在的项。与set()不同它只更新参数中指定的字段属于非破坏性更新不会影响目标位置的其他字段const itemsRef db.list(items); // 若要获取 key可参考下文“完整示例” itemsRef.update(key-of-some-data, { size: newSize });6.4 删除单项remove(key)使用remove()删除列表项位置上的数据const itemsRef db.list(items); // 若要获取 key可参考下文“完整示例” itemsRef.remove(key-of-some-data);6.5 删除整个列表省略remove()的key参数即可删除整个列表const itemsRef db.list(items); itemsRef.remove();从AngularFireList接口可以看到remove(item?: FirebaseOperation)的参数是可选且可空item?: FirebaseOperation不传参时删除整条路径见 interfaces.ts。删除整个列表操作风险较大建议配合数据库安全规则谨慎使用。7. 完整示例应用下面是一个把读、写操作整合到单个组件中的完整示例通过snapshotChanges()map把每个快照的key合并进数据对象从而在模板中直接使用item.key完成更新与删除push添加新项remove()不传参清空整个列表import { Component } from angular/core; import { AngularFireDatabase, AngularFireList } from angular/fire/compat/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); // 使用 snapshotChanges().map() 来保存 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(); } }这里的关键模式是snapshotChanges()保留每个 action 的key随后通过展开运算符...c.payload.val()把数据字段与key合并成一个可渲染、可操作的对象。这也是官方推荐的、用于“既能渲染列表、又能拿到 key 做增删改”的标准姿势。8. 与对象绑定AngularFireObject的取舍在 对象数据指南 中可以看到AngularFireObject适合同步单个对象但当涉及排序需求时请优先考虑列表因为AngularFireObject同步出来的只是单个 JSON 对象查询的排序结果不会在本地保留顺序。凡是需要分页、排序、过滤的场景都应使用本文的AngularFireList及查询能力querying-lists.md。9. 下一步查询列表列表的实时同步解决了“读”与“写”的基本问题但生产环境往往还需要按条件过滤与排序——例如只取size为large的项、限制返回条数等。这正是下一篇指南的主题查询列表Querying lists其中会讲解基于orderByChild、equalTo、limitToFirst/Last、startAt/endAt的查询构造以及用 RxJSswitchMap实现动态查询的完整方案。赞分享后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载相关推荐AngularFire 实时数据库对象操作全指南AngularFireObject 的绑定、实时订阅与增删改AngularFire 实时数据库对象操作全指南AngularFireObject 的绑定、实时订阅与增删改 本文是 AngularFireAngular后端AngularFire Realtime Database 列表数据实战指南AngularFireList 的读取、写入与删除全解析AngularFire Realtime Database 列表数据实战指南AngularFireList 的读取、写入与删除全解析 本篇指南以 Angula后端PixelStreamingInfrastructure信令协议权威参考20种WebSocket消息类型逐条拆解v1.1PixelStreamingInfrastructure信令协议权威参考20种WebSocket消息类型逐条拆解v1.1 PixelStreamingI上一篇IronClaw 完全指南隐私优先的 Rust 个人 AI 助手安装、配置与架构解析下一篇3个场景解锁clawPDF从拖拽打印到自动化OCR的工作流革命创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表