ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AngularFire 兼容层 Realtime Database 对象绑定实战:用 AngularFireObject 实时读写与同步对象数据

AngularFire 兼容层 Realtime Database 对象绑定实战:用 AngularFireObject 实时读写与同步对象数据 后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载本文是 AngularFire compat兼容层Realtime Database 系列指南的第二篇围绕AngularFireObject服务讲解如何在 Angular 应用中把 Firebase Realtime Database 的单个节点绑定为响应式对象实时读取、set/update/remove三种写操作、Promise 链式调用以及通过snapshotChanges()获取原始 DataSnapshot 元数据。读完本文你将掌握db.object()的完整用法并能与后续的列表list绑定、列表查询指南衔接使用。注意本仓库中 AngularFire 已提供新的 tree-shakable API见 README.md本文面向的是库的 compatibility 版本文档API 包名为angular/fire/compat/database。关于新旧 API 的差异可参阅 v7 升级指南。概述什么是AngularFireObjectAngularFireObject是一个用于操纵和流式输出stream单个对象数据的服务它封装了 Firebase Realtime Database 中某个路径节点上的实时同步能力。与AngularFireList见 列表文档不同它绑定的是一个对象而非一个数组适合表示单个实体例如一条用户资料、一个商品详情、一个配置项。关键点在于AngularFireObject并不是独立创建出来的而是通过AngularFireDatabase服务生成的。调用db.object(path)即可获得一个对象绑定。从源码看AngularFireObjectT的接口定义在 src/compat/database/interfaces.ts暴露以下能力export interface AngularFireObjectT { query: DatabaseQuery; valueChanges(): ObservableT | null; snapshotChanges(): ObservableSnapshotActionT; update(data: PartialT): Promisevoid; set(data: T): Promisevoid; remove(): Promisevoid; }其中query是对应的firebase.database.Query四个方法分别对应实时读取、快照读取与三种写操作。注入AngularFireDatabase服务要使用对象绑定首先需要确保应用已完成 AngularFire 的引导初始化bootstrap具体步骤见 安装与配置指南。随后AngularFireDatabase可以像普通 Angular 服务一样通过组件构造函数或Injectable()服务注入。import { Component } from angular/core; import { AngularFireDatabase } from angular/fire/compat/database; import { Observable } from rxjs; Component({ selector: app-root, templateUrl: app.component.html, styleUrls: [app.component.css] }) export class AppComponent { items: Observableany[]; constructor(db: AngularFireDatabase) { this.items db.list(items).valueChanges(); } }在模块层面AngularFireDatabaseModule会将AngularFireDatabase注册为 provider见 src/compat/database/database.module.tsNgModule({ providers: [ AngularFireDatabase ] }) export class AngularFireDatabaseModule { constructor() { firebase.registerVersion(angularfire, VERSION.full, rtdb-compat); } }下面我们将把app.component.ts改为以对象形式读取数据。创建对象绑定创建一个对象绑定非常直接调用AngularFireDatabase的object()方法即可const relative db.object(item).valueChanges();object()方法的第一个参数是PathReference类型——既可以是字符串路径也可以直接传入一个firebase.database.Reference。从 src/compat/database/database.ts 的实现可以看到路径最终通过getRef归一化为数据库引用objectT(pathOrRef: PathReference): AngularFireObjectT { const ref inject(NgZone).runOutsideAngular(() getRef(this.database, pathOrRef)); return createObjectReferenceT(ref, this, this.injector); }而 src/compat/database/utils.ts 中的getRef会判断传入的是引用还是字符串export function getRef(database: firebase.database.Database, pathRef: PathReference): DatabaseReference { return isFirebaseRef(pathRef) ? pathRef as DatabaseReference : database.ref(pathRef as string); }因此db.object(item)与db.object(database.ref(item))是等效的。实时读取数据要获得对象的实时同步把对象绑定声明为组件或服务的属性然后在模板中用 Angular 的async管道解包绑定值import { Component } from angular/core; import { AngularFireDatabase } from angular/fire/compat/database; import { Observable } from rxjs; Component({ selector: app-root, template: h1{{ (item | async)?.name }}/h1 , }) export class AppComponent { item: Observableany; constructor(db: AngularFireDatabase) { this.item db.object(item).valueChanges(); } }valueChanges 的底层行为valueChanges()是对象绑定的默认读取方式它会把 Firebase 的DataSnapshot解包unwrap成纯 JSON 数据。查看 src/compat/database/object/create-reference.ts 的实现可以发现两个值得注意的细节valueChangesT() { const snapshotChanges$ createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)(); return snapshotChanges$.pipe( pendingUntilEvent(injector), map(action action.payload.exists() ? action.payload.val() as T : null) ); }节点不存在时返回null底层会先判断action.payload.exists()只有快照存在时才返回val()否则发出null。因此模板中建议使用?.安全导航如上例的(item | async)?.name。SSR 待定事件pendingUntilEvent用于 Angular 服务端渲染SSR场景保证在首个事件到达前页面不会提前完成渲染避免水合hydration时的内容闪烁。保存数据API 汇总下表列出AngularFireObject上最常用的几个方法方法说明set(value: T)用参数指定的新值替换数据库中当前位置的现有值。这被称为破坏性destructive更新因为它会删除当前位置已有的全部数据再写入新值。update(value: T)用参数指定的新值更新当前值。这被称为非破坏性non-destructive更新因为它只更新指定字段不影响其他字段。remove()删除该位置上的所有数据等价于调用set(null)。这三个方法在源码中都是对 Firebase SDK 引用方法的直接透传见 src/compat/database/object/create-reference.tsupdate(data: PartialT) { return query.ref.update(data as any) as Promisevoid; }, set(data: T) { return query.ref.set(data) as Promisevoid; }, remove() { return query.ref.remove() as Promisevoid; },使用set()保存数据破坏性更新const itemRef db.object(item); itemRef.set({ name: new name!});使用update()更新数据非破坏性更新const itemRef db.object(item); itemRef.update({ age: newAge });注意update()只接受对象不接受原始值primitive。原因在于用原始值做update与用原始值做set效果完全相同因此 Firebase SDK 会直接拒绝这种用法。使用remove()删除数据const itemRef db.object(item); itemRef.remove();完整示例应用下面是一个将读取、保存、更新、删除四种操作组合起来的完整组件示例可直接复制到app.component.ts中运行import { Component } from angular/core; import { AngularFireDatabase, AngularFireObject } from angular/fire/compat/database; import { Observable } from rxjs; Component({ selector: app-root, template: h1{{ item | async | json }}/h1 input typetext #newname placeholderName / input typetext #newsize placeholderSize / br / button (click)save(newname.value)Set Name/button button (click)update(newsize.value)Update Size/button button (click)delete()Delete/button , }) export class AppComponent { itemRef: AngularFireObjectany; item: Observableany; constructor(db: AngularFireDatabase) { this.itemRef db.object(item); this.item this.itemRef.valueChanges(); } save(newName: string) { this.itemRef.set({ name: newName }); } update(newSize: string) { this.itemRef.update({ size: newSize }); } delete() { this.itemRef.remove(); } }返回 Promise链式操作与错误捕获上表中的每个写操作方法都会返回一个Promise。不过由于 Realtime Database 会持续保持对象同步你很少需要依赖 Promise 完成回调来判断写入成功——数据本身已经实时反映在绑定上了。Promise 的真正价值在于链式组合多个写操作捕获安全规则security rules拒绝导致的错误作为调试手段。const promise db.object(item).remove(); promise .then(_ console.log(success)) .catch(err console.log(err, You dont have access!));当 Firebase 安全规则拒绝该写操作时错误会从 Promise 的catch分支抛出你可以借此向用户提示权限不足等信息。获取原始快照snapshotChanges()默认情况下valueChanges()会解包 DataSnapshot只返回纯数据。如果你需要保留快照元数据例如key、type以及完整的payload快照可以使用snapshotChanges()this.itemRef db.object(item); this.itemRef.snapshotChanges().subscribe(action { console.log(action.type); console.log(action.key) console.log(action.payload.val()) });action是一个SnapshotActionT其结构定义在 src/compat/database/interfaces.ts包含type监听事件类型、payloadDataSnapshot、key与prevKey。从源码看snapshotChanges()内部通过 src/compat/database/object/snapshot-changes.ts 的createObjectSnapshotChanges创建流export function createObjectSnapshotChangesT(query: DatabaseQuery, scheduler?: SchedulerLike) { return function snapshotChanges(): ObservableSnapshotActionT { return fromRef(query, value, on, scheduler); }; }它复用了 src/compat/database/observable/fromRef.ts 中的fromRef工具函数监听value事件使用on监听模式持续接收更新并在取消订阅时调用ref.off(event, fn)解除监听见 fromRef 的unsubscribe实现通过share()运算符共享同一数据源多个订阅者不会重复建立监听调度器使用afDatabase.schedulers.outsideAngular让数据回调在 Angular Zone 之外调度避免频繁触发变更检测相关代码见 create-reference.ts。关于查询Querying的说明因为AngularFireObject是从 Realtime Database 同步一个对象所以排序对于没有同时附加范围range限制的查询没有意义。举例来说分页时需要同时提供排序和过滤条件——排序与过滤共同决定了查询返回哪部分数据但由于最终得到的对象只是普通 JSON排序顺序不会在本地保留。因此如果你的需求涉及排序操作那么你需要的很可能是 列表list绑定而不是对象绑定。小结与下一步本文完整覆盖了AngularFireObject的核心用法通过db.object()创建对象绑定实时读取节点数据set破坏性、update非破坏性、remove等价于set(null)三种写操作Promise 用于链式操作与安全规则错误捕获snapshotChanges()获取含type、key、payload的原始快照排序需求应转向列表绑定。下一步以列表形式读取数据对象只对应单个节点当需要处理一组数据例如所有商品消息列表时请继续阅读 以列表形式读取数据lists了解AngularFireList的push、update、remove以及valueChanges()/snapshotChanges()/stateChanges()/auditTrail()等基于 Action 的 API。赞分享后端【免费下载链接】angularfireAngular Firebase ❤️项目地址https://gitcode.com/gh_mirrors/an/angularfire点击查看免费下载相关推荐es-toolkit 兼容层 bindAll 详解如何把对象的 this 批量绑定到对象自身es toolkit 兼容层 bindAll 详解如何把对象的 this 批量绑定到对象自身 本文基于 es toolkit 官方兼容层文档 docs/ja/前端后端GrapesJS数据绑定终极指南复杂对象双向绑定实战GrapesJS数据绑定终极指南复杂对象双向绑定实战 GrapesJS作为一款免费开源的Web构建框架让开发者无需编写代码就能创建精美的网页模板。本文将深入前端低代码UI组件PostHog 的 GitHub Actions 实战Depot 托管 Runner 的选型、缓存与调试全指南PostHog 的 GitHub Actions 实战Depot 托管 Runner 的选型、缓存与调试全指南 本文以 PostHog 仓库内置的技能文档 S数据分析后端前端数据可视化大数据上一篇中兴光猫终极解锁工具zteOnu 工厂模式与Telnet永久开启完整指南下一篇Sunshine游戏串流完整指南5步搭建你的私人云游戏平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表