ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RxDB 与 Vue 3 集成实战:构建带 CouchDB 实时同步的英雄列表应用

RxDB 与 Vue 3 集成实战:构建带 CouchDB 实时同步的英雄列表应用 数据库NoSQL嵌入式数据库实时数据库【免费下载链接】rxdbThe local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/项目地址https://gitcode.com/gh_mirrors/rx/rxdb点击查看免费下载本文以 RxDB 仓库中的 Vue 示例 为蓝本完整讲解如何在 Vue 3 TypeScript 应用中接入 RxDB包括本地数据库初始化、Schema 与类型定义、响应式查询、ORM 方法、插入/编辑/删除流程以及通过 CouchDB 协议与pouchdb-server实现的实时双向同步。读完本文你将能独立复刻一套本地优先local-first、多端实时同步的 Vue 应用骨架并理解其背后每个环节的源码实现。示例项目概览examples/vue是一个 RxDB 官方仓库中的最小可运行示例它实现了一个英雄列表heroes-list应用用户可以输入英雄的名字与颜色提交后英雄被写入本地 RxDB 数据库并在列表中实时渲染列表项支持编辑血量HP与删除同时应用会通过 CouchDB 协议把数据同步到本地pouchdb-server。整个项目还演示了多标签页multitab下的 Leader Election 行为。项目核心目录结构相对仓库根目录examples/vue/src/database/index.ts数据库创建、插件装配、集合注册、Hook 与同步逻辑examples/vue/src/schemas/Hero.schema.ts英雄集合的 RxJsonSchema 定义examples/vue/src/RxDB.d.ts为 Schema 字段与 ORM 方法补充的 TypeScript 类型examples/vue/src/components/HeroList、HeroInsert、HeroEdit 三个业务组件examples/vue/test/e2e.test.js基于 TestCafe 的端到端测试examples/vue/package.json脚本与依赖清单环境准备与运行步骤原文档给出了从克隆仓库到页面打开的完整 7 步流程下面逐条展开并补充每步背后的作用克隆整个 RxDB 仓库git clone https://gitcode.com/gh_mirrors/rx/rxdb进入项目根目录并安装依赖、构建 RxDB 主库cd rxdb npm install npm run build这一步会构建出 RxDB 核心包的产物供示例通过本地打包文件引用。进入示例目录cd examples/vue执行预安装与安装npm run preinstall npm installpreinstall脚本见 examples/vue/package.json执行的是(cd ../../ npx yarn1.22.22 pack ../../ --filename ./examples/vue/rxdb-local.tgz)它把仓库根目录的 RxDB 源码打包成本地rxdb-local.tgz随后npm install通过依赖rxdb: file:rxdb-local.tgz安装这份本地构建产物。package.json 中有一行醒目的注释说明了这一设计在 GitHub CI 中使用本地 RxDB 构建产物而真实项目中应当直接从 npm 安装rxdb。启动应用npm startstart脚本通过concurrently同时拉起两个进程见 examples/vue/package.jsonserverpouchdb-server --host 0.0.0.0 -p 10101 -m -d /tmp/pouchdb-server/ -n true即在 10101 端口启动一个兼容 CouchDB 协议的本地同步服务端devvue-cli-service serve即 Vue CLI 开发服务器。浏览器打开应用地址http://127.0.0.1:8080/重要不要使用localhost访问。原因可以从源码推断数据库初始化时同步地址由window.location.hostname动态拼接而成见 examples/vue/src/database/index.tsconst syncURL http:// window.location.hostname :10101/;若用localhost打开页面浏览器可能将其解析为 IPv6 的::1而pouchdb-server监听在0.0.0.0两者可能导致同步请求无法连通使用127.0.0.1可确保前端与同步服务端之间的地址一致。数据库初始化与插件装配数据库的全部初始化逻辑集中在 examples/vue/src/database/index.ts。它展示了 RxDB 典型的插件化装配方式1. 按环境加载插件import { RxDBDevModePlugin } from rxdb/plugins/dev-mode; if (process.env.NODE_ENV development) { // in dev-mode we add the dev-mode plugin // which does many checks and adds full error messages addRxPlugin(RxDBDevModePlugin); } import { RxDBLeaderElectionPlugin } from rxdb/plugins/leader-election; addRxPlugin(RxDBLeaderElectionPlugin);RxDBDevModePlugin仅在开发环境加载它会在运行时做大量 Schema、查询与存储一致性检查并输出完整的错误消息帮助尽早发现问题参见 dev-mode 插件文档RxDBLeaderElectionPlugin提供多标签页/多实例下的 Leader 选举能力示例用它来标记当前哪个标签页是 Leaderdb.waitForLeadership().then(() { console.log(isLeader now); document.title ♛ document.title; });2. 创建数据库与存储引擎const db await createRxDatabaseRxHeroesCollections({ name: heroes, storage: wrappedValidateAjvStorage({ storage: getRxStorageLocalstorage() }) // password: myLongAndStupidPassword // no password needed });name: heroes是数据库名存储层使用了wrappedValidateAjvStorage包裹getRxStorageLocalstorage()外层负责在写入前用 AJV 按 Schema 校验文档内层storage-localstorage把数据持久化到浏览器 LocalStorage参见 rx-storage-localstorage 与 rx-storage.mdpassword字段被注释掉说明该示例未启用加密需要加密时可参考 encryption.md。创建完成后示例还把db挂到window上便于在控制台调试(window as any).db db;3. 注册集合与 ORM 方法await db.addCollections({ heroes: { schema: heroSchema, methods: { hpPercent(this: RxHeroDocument): number { return (this.hp / this.maxHP) * 100; }, }, }, });methods为集合文档注册 ORM 方法hpPercent()计算当前血量百分比之后任何hero文档实例都能直接调用hero.hpPercent()见 HeroList.vue 中生命条宽度的计算。4. 写入前 Hook颜色唯一性校验db.collections.heroes.preInsert((docObj: RxHeroDocumentType) { const color docObj.color; return db.collections.heroes .findOne({ selector: { color } }) .exec() .then((has: RxHeroDocument | null) { if (has ! null) { alert(another hero already has the color color); throw new Error(color already there); } return db; }); }, true);preInsertHook 在每次插入前查询同色英雄若已存在则弹窗提示并抛出错误阻止写入。第二个参数true表示该 Hook 为异步返回 PromiseRxDB 会等待其完成后再执行真正的写入。5. 以 Vue 插件形式注入createDatabase()最终返回一个实现了 VuePlugin接口的对象return { install(app: any) { app.provide(KEY_DATABASE, db); }, };结合 main.tsconst database createDatabase(); const app createApp(App).use(router); database.then(db { app.use(db).mount(#app); });数据库就绪后通过app.use(db)注入全局业务组件内用useDatabase()内部调用inject(KEY_DATABASE)即可拿到类型安全的数据库实例——这是 Vue 3 Composition API 下管理 RxDB 单例的推荐模式。Schema 定义与 TypeScript 类型系统英雄集合的 RxJsonSchemaexamples/vue/src/schemas/Hero.schema.ts 定义了heroes集合的完整 Schemaconst schema: RxJsonSchemaRxHeroDocumentType { title: hero schema, description: describes a simple hero, version: 0, keyCompression: false, primaryKey: name, type: object, properties: { name: { type: string, default: , maxLength: 100 }, color: { type: string, default: }, maxHP: { type: number, minimum: 0, maximum: 1000 }, hp: { type: number, minimum: 0, maximum: 100, default: 100 }, team: { description: color of the team this hero belongs to, type: string }, skills: { type: array, maxItems: 5, uniqueItems: true, items: { type: object, properties: { name: { type: string }, damage: { type: number }, }, }, default: [], }, }, required: [color, hp, maxHP, skills], };关键字段说明字段约束含义primaryKeyname以name作为主键主键字段必须是字符串且唯一version0Schema 版本号升级 Schema 时需递增并配合迁移逻辑参见 migration-schema.mdkeyCompressionfalse示例未开启键压缩生产环境可参考 key-compression.md 减小存储体积maxHP0 ~ 1000最大血量数值范围hp0 ~ 100默认100当前血量skills数组maxItems: 5、uniqueItems: true技能列表最多 5 项且不重复required四个必填字段缺任一字段时校验失败自定义类型声明examples/vue/src/RxDB.d.ts 为 Schema 字段与 ORM 方法补齐了强类型避免业务代码里到处anyexport interface RxHeroDocumentType { name: string; color: string; maxHP: number; hp: number; team?: string; skills: Array{ name?: string; damage?: string }; } interface RxHeroDocMethods { hpPercent(): number; } export type RxHeroDocument RxDocumentRxHeroDocumentType, RxHeroDocMethods; export type RxHeroCollection RxCollectionRxHeroDocumentType, RxHeroDocMethods, {}; export interface RxHeroesCollections { heroes: RxHeroCollection; } export type RxHeroesDatabase RxDatabaseRxHeroesCollections;这样useDatabase()返回的RxHeroesDatabase、集合查询得到的RxHeroDocument[]都具备完整的字段与方法类型提示。Vue 组件中的响应式查询与文档操作列表查询把 RxQuery 可观察对象桥接到 Vue refHeroList.vue 演示了 RxDB 最核心的响应式能力——查询结果随数据库变化自动更新const sub database.heroes .find({ selector: {}, sort: [{ name: asc }] }) .$.pipe( tap(() { // debounce to simulate slow load setTimeout(() (loading.value false), 1000); }) ) .subscribe((result: RxHeroDocument[]) { heroes.value result; }); onUnmounted(() { if (sub) { sub.unsubscribe(); } });要点find({ selector: {}, sort: [{ name: asc }] })返回 RxQuery$.是它的可观察对象任何文档插入、更新、删除都会推送最新结果数组参见 rx-query.md 与 reactivity.md通过tap延迟 1 秒关闭 loading 状态模拟慢加载的视觉反馈组件卸载时必须unsubscribe()释放订阅避免内存泄漏列表项展示hero.hpPercent()计算的生命条宽度删除按钮直接调用文档方法hero.remove()。插入构建文档对象HeroInsert.vue 在表单提交时构造文档并调用insertconst obj { name: hero.value.name, color: hero.value.color, hp: 100, maxHP: randomInt(100, 1000), skills: [] }; await database.heroes.insert(obj);maxHP使用random-int包在 1001000 之间随机生成skills默认空数组正好满足 Schema 的required约束。插入后的文档会立即触发前面HeroList的查询订阅。编辑冲突检测与增量更新HeroEdit.vue 展示了多端同步场景下的冲突处理思路// 文档被外部改变如另一标签页或同步端 firstValueFrom( props.hero.$.pipe( skip(1), map(() false) ) ).then((v: boolean) (synced.value v)); // 文档被删除 firstValueFrom(props.hero.deleted$).then(() (deleted.value true));订阅hero.$文档级可观察对象并skip(1)跳过初始值一旦文档被其他端修改就置synced false界面上弹出Someone else has changed this document警告订阅hero.deleted$若文档被他人删除则禁止继续保存保存时使用hero.incrementalPatch({ hp: props.hero.hp })做增量更新比全量覆盖更安全、更高效参见 rx-document.md。页面装配Home.vue 用v-model:heroedit把待编辑英雄传给HeroEdit并通过edit/cancel/submit事件协调三个组件的交互状态。CouchDB 实时双向同步示例的同步链路是浏览器 LocalStorageRxDB 存储层→replicateCouchDB→pouchdb-server10101 端口。同步代码位于 examples/vue/src/database/index.ts分两步第一步为每个集合在 CouchDB 服务端创建同名数据库PUT 请求await Promise.all( Object.values(db.collections).map(async (col) { try { await fetch(syncURL col.name /, { method: PUT }); } catch (err) { console.dir(err); } }) );第二步对每个集合启动replicateCouchDB实时复制const replicationState replicateCouchDB({ replicationIdentifier: my-vue-couch-replication, collection: col, url, live: true, pull: {}, push: {}, autoStart: true }); replicationState.error$.subscribe((err: any) { console.log(Got replication error:); console.dir(err); });参数说明replicationIdentifier复制状态在本地持久化时的唯一标识用于断点续传live: true开启实时监听本地改动推送到远端、远端改动拉回本地pull/push分别控制拉取与推送的行为空对象表示默认行为可在这里配置过滤函数实现部分同步参见 partial-sync.mdautoStart: true创建后立即开始复制replicationState.error$订阅复制过程中的错误流便于排查网络或协议问题。更完整的复制协议与冲突处理机制可参见 replication-couchdb.md、replication.md 与 transactions-conflicts-revisions.md。本地存储仅使用storage-localstorage时建议先阅读 rx-storage-localstorage-meta-optimizer.md了解多实例同步对存储实现的额外要求。端到端测试验证 CRUD、多标签页与 Leader Electionexamples/vue/test/e2e.test.js 用 TestCafe 覆盖了示例的三个关键行为测试 1插入 / 编辑 / 删除英雄输入BobKelso与颜色black并提交断言列表中文本包含Kelso随后点击垃圾桶图标删除断言列表项数量归零对应npm test中的test:run脚本。测试 2多标签页同步打开multitab.html?frames2在 iframe#frame_0插入英雄SteveIrwin切换到#frame_1断言列表中出现该名字——验证同一个浏览器存储下多个标签页能实时看到彼此的写入。测试 3Leader Election打开 6 个 iframe断言恰好有一个标签页标题带♛标记Leader通过#removeId输入框杀掉当前 Leader 后其余标签页中会重新产生一个新的 Leader且仍然只有一个。这正是RxDBLeaderElectionPlugin与waitForLeadership()行为的端到端验证参见 leader-election.md。脚本与依赖清单速览examples/vue/package.json 中的脚本分工脚本命令用途preinstall打包仓库根目录 RxDB 为rxdb-local.tgz用本地构建产物替代 npm 包startconcurrently npm run server npm run dev同时启动同步服务端与 Vue 开发服务器serverpouchdb-server --host 0.0.0.0 -p 10101 -m -d /tmp/pouchdb-server/ -n true启动 CouchDB 兼容服务端devvue-cli-service serveVue CLI 开发服务器默认 8080 端口buildvue-cli-service build生产构建build:servews -p 8888 -d dist/用 local-web-server 在 8888 端口预览构建产物test并发启动 server、build:serve 与 test:run一键跑端到端测试运行时依赖包括vue3.5.42、rxjs7.8.2RxDB 的响应式依赖、rxdb本地 tgz、pouchdb-server4.2.0、vue-router与random-int开发依赖则包含vue/cli-service、typescript、testcafe、async-test-util等。若要把这套架构迁移到真实项目只需把rxdb: file:rxdb-local.tgz换成 npm 上的正式版本并将同步地址指向真实的 CouchDB/兼容服务端即可。赞分享数据库NoSQL嵌入式数据库实时数据库【免费下载链接】rxdbThe local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/项目地址https://gitcode.com/gh_mirrors/rx/rxdb点击查看免费下载相关推荐RxDB CouchDB 复制插件实战用 Sync Engine 对接 CouchDB 的高效实时同步方案RxDB CouchDB 复制插件实战用 Sync Engine 对接 CouchDB 的高效实时同步方案 replicateCouchDB 是 RxDB 官数据库NoSQL嵌入式数据库实时数据库React Native Database 实战用 RxDB 构建离线优先、实时同步的移动应用React Native Database 实战用 RxDB 构建离线优先、实时同步的移动应用 RxDB 是一个 local first 的 NoSQL 文档数据库NoSQL嵌入式数据库实时数据库RxDB实时数据同步构建多用户协作应用的最佳实践RxDB实时数据同步构建多用户协作应用的最佳实践 RxDB通过其强大的实时同步协议和冲突解决机制为构建多用户协作应用提供了完整的解决方案。本文深入探讨了Rx数据库NoSQL嵌入式数据库实时数据库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表