news 2026/4/23 11:18:50

Yjs 前端实时协作库学习笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Yjs 前端实时协作库学习笔记

核心定位

纯前端 / Node.js 通用的实时协作数据一致性库,基于 CRDT(无冲突复制数据类型)实现,核心解决「多人同时修改数据、断网离线修改数据」后的数据自动统一问题,是前端开发在线文档、白板、表格等协作类应用的核心工具,也是 BlockSuite 实时协作能力的底层内核。

简单说:给普通 JS 数据加「协作外挂」,改数据时自动同步、自动解决冲突,开发者不用写分布式、冲突解决、数据同步的代码,专注业务即可。

一、核心特性(大白话版)

  1. CRDT 底层,无需服务端强同步:每个客户端存一份完整数据副本,冲突本地自动计算,最终所有设备数据一致;对比 OT 技术,不用服务端做复杂操作转换,开发更简单。
  2. 兼容前端常用数据类型:支持数组、键值对、树形结构等,操作方法和普通 JS 数据几乎一致,低成本替换原有数据。
  3. 通信完全解耦:只负责「生成同步的小数据片段」,不管「数据怎么传」,WebSocket、WebRTC、小程序通信等都能适配。
  4. 原生支持离线编辑:自动将数据存在浏览器 IndexedDB,断网修改不丢失,联网后自动重连并同步本地修改。
  5. 前端无缝集成:TS/JS 原生支持,体积小,和 Vue/React/ 原生前端、Web Components 都能完美搭配。

二、核心依赖安装

bash

运行

# 核心库(必须装) npm install yjs # 官方 WebSocket 通信插件(快速实现多人协作,无需自己开发服务端,推荐必装) npm install y-websocket

三、核心概念(3 个核心,记牢即可)

1. Y.Doc - 共享数据容器

所有 Yjs 共享数据的根容器,是协作的核心入口。

  • 每个协作文档对应一个唯一标识,不同客户端用相同标识就能同步数据;
  • 每个客户端都要创建一份 Y.Doc,内部维护分布式共享数据。

2. 共享数据类型 - 替换普通 JS 数据

Yjs 提供专属的「共享数据类型」,替换原有 JS 数组 / 对象 / 树,操作方法几乎一致,修改后会自动标记同步片段。

Yjs 共享类型对应普通 JS 类型适用场景
Y.Array数组存列表数据(如 BlockSuite 块列表)
Y.Map对象 / Map存键值对数据(如用户信息、块属性)
Y.XmlFragment/Y.XmlElement树形结构存层级数据(如 BlockSuite 块树、富文本节点)

3. observe - 数据变化监听

监听共享数据的所有修改(本地修改 / 远端协作方修改都会触发),是「数据驱动视图」的核心,通过监听事件实现视图精准更新。

四、核心代码片段(极简实用,直接复制可运行)

片段 1:基础使用 - 创建共享数据 + 本地修改监听

实现普通 JS 数据的「共享化」,掌握基础的增删改和监听逻辑。

javascript

运行

import * as Y from 'yjs'; // 1. 创建共享文档容器 const yDoc = new Y.Doc(); // 2. 创建共享数据(替换普通 JS 数组/Map) const yArr = yDoc.getArray('myList'); // 共享数组 const yMap = yDoc.getMap('myInfo'); // 共享键值对 // 3. 监听数据变化(本地/远端修改统一触发) yArr.observe((event) => { console.log('数组数据变化:', event); console.log('最新数组(转普通 JS):', yArr.toArray()); // 转普通 JS 供视图渲染 }); // 4. 操作共享数据(和普通 JS 用法几乎一致) yArr.push(['苹果', '香蕉']); // 新增元素 yArr.set(0, '红苹果'); // 修改元素 yMap.set('author', '张三'); // Map 设值 // 5. 转换为普通 JS 数据(视图渲染专用,Yjs 数据不能直接绑视图) console.log(yArr.toArray()); // ['红苹果', '香蕉'] console.log(yMap.toJSON()); // { author: '张三' }

片段 2:多人协作核心 - WebSocket 通信桥接

3 行代码实现多端同步,不用自己开发服务端,打开多个浏览器窗口即可测试协作效果。

javascript

运行

import * as Y from 'yjs'; import { WebsocketProvider } from 'y-websocket'; // 1. 创建共享文档 const yDoc = new Y.Doc(); const yArr = yDoc.getArray('collabList'); // 2. 连接官方测试服务端(一键实现通信,无需自己搭服务) // 格式:WebsocketProvider(服务端地址, 协作文档唯一标识, Yjs文档) const provider = new WebsocketProvider( 'wss://demos.yjs.dev', // Yjs 官方免费测试服务端 'my-first-collab-doc', // 同一协作文档用相同标识,不同客户端自动同步 yDoc ); // 3. 监听协作连接状态(可选,做加载/离线提示) provider.on('status', (event) => { console.log('协作连接状态:', event.status); // connected / disconnected / connecting }); // 4. 任意客户端修改,其他客户端实时同步 yArr.push(['协作数据1', '协作数据2']);

片段 3:精准监听 - 增 / 删 / 改单独处理(适配视图精准更新)

实际开发无需全量渲染视图,通过 Yjs 事件精准获取「哪里变了、变了什么」,实现 BlockSuite 同款「精准视图更新」。

javascript

运行

import * as Y from 'yjs'; const yDoc = new Y.Doc(); const yBlocks = yDoc.getArray('blocks'); // 模拟 BlockSuite 块列表 // 精准监听数组的增、删、改 yBlocks.observe((event) => { // 1. 新增元素:[索引, 元素值] event.changes.added.forEach(([index, value]) => { console.log(`索引${index}新增:`, value); // 业务操作:新增对应视图节点(如 BlockSuite 新增块) }); // 2. 更新元素:仅返回索引,值从 yBlocks.get(index) 获取 event.changes.updated.forEach((index) => { const updateValue = yBlocks.get(index); console.log(`索引${index}更新为:`, updateValue); // 业务操作:更新对应视图节点(精准渲染) }); // 3. 删除元素:[索引, 被删值] event.changes.deleted.forEach(([index, value]) => { console.log(`索引${index}删除:`, value); // 业务操作:删除对应视图节点 }); }); // 测试操作(分别触发 added/updated/deleted) yBlocks.push([{ id: '1', content: '测试块1' }]); yBlocks.set(0, { id: '1', content: '修改后的块1' }); yBlocks.delete(0);

片段 4:离线编辑 + 自动重连(原生支持,无需额外代码)

Yjs 自动将数据存在浏览器 IndexedDB,断网修改不丢失,联网后自动同步,全程无需自己写本地存储、重连逻辑。

javascript

运行

import * as Y from 'yjs'; import { WebsocketProvider } from 'y-websocket'; const yDoc = new Y.Doc(); const yArr = yDoc.getArray('offlineList'); const provider = new WebsocketProvider('wss://demos.yjs.dev', 'offline-doc', yDoc); // 断网后:正常修改数据,自动存在本地 IndexedDB yArr.push(['断网编辑的内容1', '断网编辑的内容2']); // 联网后:自动重连,将本地修改同步给服务端/其他客户端,无需额外代码

片段 5:树形结构使用(和 BlockSuite 块树深度适配)

BlockSuite 的「块树」是核心,Yjs 用Y.XmlFragment/Y.XmlElement实现分布式树形结构,完美贴合块的父子层级关系。

javascript

运行

import * as Y from 'yjs'; const yDoc = new Y.Doc(); // 创建共享树形结构(模拟 BlockSuite 根块树) const yBlockTree = yDoc.getXmlFragment('blockTree'); // 1. 创建块节点(设置块类型、属性) const titleBlock = Y.XmlElement('text'); // 节点类型=块类型(text/Image/table) titleBlock.setAttribute('id', 'title1'); // 块唯一ID titleBlock.setAttribute('content', 'BlockSuite 标题块'); // 块内容 const contentBlock = Y.XmlElement('text'); contentBlock.setAttribute('id', 'content1'); contentBlock.setAttribute('content', 'BlockSuite 内容块'); // 2. 构建父子层级(标题块为父,内容块为子) titleBlock.insertChild(0, contentBlock); // 3. 将根节点加入块树 yBlockTree.insertChild(0, titleBlock); // 4. 监听树变化(精准到节点增删、属性修改) yBlockTree.observe((event) => { console.log('块树变化:', event); }); // 这是 BlockSuite 块树的底层实现:基于 Yjs 树形结构做分布式共享

五、Yjs 在 BlockSuite 中的核心应用

BlockSuite 把 Yjs 作为内核数据引擎,而非简单第三方依赖,核心结合点:

  1. 块数据共享化:所有块(文字 / 图片 / 表格)的属性、层级关系,都存在 Yjs 共享数据中(数组 / 树形结构);
  2. 操作标准化:BlockSuite 的 Command 命令修改块数据时,实际是修改 Yjs 共享数据,Yjs 自动生成同步片段;
  3. 统一视图更新:BlockSuite 仅监听 Yjs 数据变化,不区分修改来自「本地」还是「远端协作方」,统一触发视图精准更新;
  4. 协作通信解耦:BlockSuite 封装了 Yjs 通信接口,支持替换 WebSocket/WebRTC 等通信方式,适配不同协作场景。

六、关键总结(核心考点 / 开发要点)

  1. Yjs 核心作用:解决前端多人协作的数倨一致性,自动同步、自动解决冲突,离线编辑原生支持;
  2. 开发核心流程:创建 Y.Doc → 定义共享数据 → 监听数据变化驱动视图 → 配置通信插件实现多端同步;
  3. 核心优势:操作简单(和普通 JS 数据用法几乎一致)、视图友好(精准监听变化,支持按需渲染)、扩展灵活(通信层可自由替换);
  4. 和 BlockSuite 关系:Yjs 是 BlockSuite 实时协作的底层数据基础,BlockSuite 基于 Yjs 封装了块模型、命令系统,实现了「块式编辑 + 实时协作」的融合。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 21:44:39

STM32(7)--FPU(TODO)

1 简介2 实现1--数字低通滤波器需求: 滤掉音频里的高频刺耳噪声。 公式: $y[n] \alpha \cdot x[n] (1 - \alpha) \cdot y[n-1]$ 这就是一个最基础的差分方程,也是《信号与系统》的第一课。

作者头像 李华
网站建设 2026/4/11 20:42:47

对象存储oss

对象存储的核心概念是什么?与块存储、文件存储的区别?对象存储:存储对象(数据元数据全局唯一ID)。扁平结构,通过RESTful API访问,适合海量非结构化数据。 块存储:将数据分割成固定大…

作者头像 李华
网站建设 2026/4/11 14:45:43

【毕业设计】SpringBoot+Vue+MySQL 医药管理系统平台源码+数据库+论文+部署文档

摘要 随着信息技术的快速发展,医药行业对高效、智能的管理系统需求日益增长。传统医药管理方式依赖人工操作,存在效率低、易出错、数据难以共享等问题,尤其在药品库存、患者信息管理和处方流转等方面表现尤为突出。医药管理系统平台通过信息…

作者头像 李华
网站建设 2026/4/23 9:45:44

三极管门电路

目录 概述 核心基础:三极管非门(反相器) Multisim仿真分析 1、非门(基础门)——一个NPN 2、与非门——两个NPN 3、与门——三个NPN 核心电路结构(3 个 NPN 管,核心为 2 输入 + 1 反相) 第一步:Q1/Q2 串联 → 与非门(全 0 出 1,有 1 出 0) 第二步:Q3 反相 →…

作者头像 李华