CRDT框架,具有强大的共享数据抽象
演示: https://github.com/yjs/yjs-demos 讨论: https://discuss.yjs.dev网址 聊天室: 书写器 | 不一致 基准Yjs与自动合并: https://github.com/dmonad/crdt-benchmarks网站 播客 “Yjs深度挖掘实时协作编辑解决方案”: 播客 “使用YJS框架在古腾堡进行谷歌文档式编辑”:
与维护人员签订的支持合同 - 通过向开源Yjs项目捐款,您可以获得 直接来自作者的专业支持。 这包括以下机会 每周视频通话,讨论您的具体挑战。 Synergy代码 -专门从事 咨询和开发可视化实时协同编辑解决方案 应用程序、Synergy Codes专注于交互式图表、复杂图形、图表和 各种数据可视化类型。 他们的专业知识使开发人员能够构建 利用Yjs的强大功能,提供吸引人的交互式视觉体验。 请参见 他们在 可视化协作 展柜 .
AFFiNE公司 一个本地首个、私密首个、开放源代码 知识库。 🌟 Huly公司 -开源多功能项目管理平台 🌟 货物 设计师和艺术家的网站建设者 🌟 Gitbook(Gitbook) 技术团队的知识管理 🌟 印象笔记 笔记应用程序 🌟 课程空间 虚拟企业平台 教室和在线培训 🌟 埃利普索斯 -用于讲故事等的协作写作应用程序。 支持版本控制、更改归因和“指责”。 整体解决方案 出版过程(也包括销售) ⭐ Dynaboard公司 协同构建web应用程序。 ⭐ Relm公司 一个团队协作的游戏世界 社区。 ⭐ 房间.sh 具有集成功能的会议应用程序 协同绘图、编辑和编码工具。 ⭐ Nimbus纸币 由设计的记事本应用程序 Nimbus网。 ⭐ Pluxbox收音机管理器 基于web的应用程序 协同组织无线电广播。 ⭐ 莫迪夫 -Modyf是为以下目的构建的设计平台 多学科设计师。 设计、生成、动画等-无需 在应用程序之间切换。 ⭐ 萨那 具有协作文本的学习平台 编辑由Yjs提供支持。 宁静笔记 端到端加密 协作笔记应用程序。 减贫战略管理 协作思维映射和系统可视化。 (来源) Alldone公司 下一代项目管理和 协作平台。 生活规范 产品团队协作的现代方式。 滑动光束器 演示应用程序。 区块调查 表单/调查的端到端加密。 斯基夫 私人的、去中心化的工作空间。 JupyterLab公司 协作计算笔记本 JupyterCad公司 扩展到 JupyterLab支持协同编辑三维FreeCAD模型。 Hyperquery(超级查询) 协作数据工作区 共享分析、文档、电子表格和仪表盘。 诺斯格斯特气候 法国碳排放 足迹计算器具有基于yjs的组P2P模式 “oorja.io” 可扩展的在线会议空间 协作应用程序,端到端加密。 传奇守护者 合作活动策划人和 桌面RPG的世界建筑应用程序。 IllumiDesk公司 使用A.I.构建课程和内容。 顺便说一句 开源介质替代方案 AWS SageMaker公司 制造机器的工具 学习模型 线性的 简化问题、项目和产品路线图。 顺便说一句 -个人网站建设者 AWS SageMaker公司 -机器学习服务 阿基特 -现场采访软件 Appflowy公司 -他们使用Yrs 多应用程序 -多人应用程序共享:指向、绘制和编辑 在共享应用程序中,就像它们在您的计算机上一样。 他们正在使用Yrs。 应用程序管理器 用于创建的无代码平台 生成源代码的生产就绪应用程序。 合成 -协作视频编辑器 thinkdeli公司 -由AI支持的快速简单笔记应用程序 我们的董事会 -协作白板 申请 埃利·艾 -数据产品设计和协作 GoPeer公司 -协作辅导 屏幕.花园 PKM应用程序的协作后端。
此提供程序列表不完整。 请打开PR以将您的提供商添加到 这个列表!
y-腹板套筒 一个模块,包含一个简单的websocket后端和一个 连接到该后端。 y-redis(y-redis) , y型糖 , ypy-网络套接字 和 霍库斯波库斯 (见下文)是备选方案 后端到y-websocket。 y-webrtc公司 使用WebRTC对等传播文档更新。 同行交流 通过信令服务器发送信令数据。 公共可用的信令服务器 可用。 信令服务器上的通信可以通过以下方式加密 提供共享机密,保留连接信息和共享 文档私有。 @活动块/yjs -
Liveblocks Yjs公司 提供了一个完整的 托管WebSocket基础结构和Yjs的持久化数据存储 文件。 无需配置或维护。 它还具有 Yjs webhook事件,用于读取和更新Yjs文档的REST API,以及 浏览器DevTools扩展。 y型糖 具有S3或文件系统持久性的独立yjs服务器。 他们提供了 云服务 也。 霍库斯波库斯 具有sqlite持久性、webhooks、auth等功能的独立可扩展yjs服务器。 party工具包 用于构建多人应用程序的云服务。 y-libp2p 使用 libp2p 通过传播更新 八卦订阅 . 还包括一个对等同步机制,以赶上错过的更新。 y-日期 [WIP]使用 多点供油的 。每个客户都有 CRDT本地更新的附加日志(超核心)。 Multifeed管理和同步 hypercores和y-dat侦听更改并将其应用于Yjs文档。 矩阵-CRDT 使用 矩阵 作为的离线后端 Yjs通过使用 矩阵提供者 . 使用Matrix作为Yjs更新的传输和存储,这样您可以专注于构建 您的客户端应用程序和Matrix可以提供强大的功能,如身份验证、, 授权、联合、托管(自托管或SaaS)甚至端到端 加密(E2EE)。 yrb-可操作 Yjs客户端的ActionCable伴侣。 有一个配件 redis扩展 也。 ypy-网络套接字 Websocket后端,用Python编写。 微型底座 本地首批应用程序的反应式数据存储。 它们支持多个CRDT 不同的网络技术。 y-webxdc 用于在中共享数据的提供程序 webxdc聊天应用程序 .
y索引b 高效地将文档更新持久化到浏览器indexeddb数据库。 文档立即可用,只需要通过 网络提供商。 y-mongodb-提供者 使用MongoDB向服务器添加永久存储。 可与一起使用 y-websocket提供程序。 @toeverything/y-indexeddb 与y-indexeddb类似,但具有子文档支持和完全TypeScript。 五火 基于Firestore的Yjs数据库和连接提供程序。 y-op-硅藻土 使用在React Native应用程序中持久化YJS更新 硅藻土 是React Native最快的SQLite库。 y-postgresql格式 使用PostgreSQL和 很容易与y-websocket兼容。
npm i yjs y网络套接字
端口=1234节点/ 节点模块/y-websocket/bin/server.cjs
进口 * 作为 年 从 “是的” ;
常数 文件 = 新的 年 . 文件 ( ) ;
常数 亚雷 = 文件 . 获取数组 ( '我的阵列' )
亚雷 . 观察 ( 事件 => {
慰问 . 日志 ( “yarray已修改” )
} )
//每次本地或远程客户端修改yarray时,都会调用观察者
亚雷 . 插入 ( 0 , [ “val” ] ) //=>“yarray被修改”
常数 我的妈妈 = 文件 . 获取地图 ( “地图” )
常数 食物数组 = 新的 年 . 阵列 ( )
食物数组 . 插入 ( 0 , [ “苹果” , “香蕉” ] )
我的妈妈 . 设置 ( “食物” , 食物数组 )
我的妈妈 . 得到 ( “食物” ) === 食物数组 //=>真
我的妈妈 . 设置 ( “水果” , 食物数组 ) //=>错误! 已定义foodArray
进口 * 作为 年 从 “是的”
进口 { Webrtc提供商 } 从 “y-webrtc”
进口 { Websocket提供者 } 从 'y-websocket'
进口 { 索引ddb持久性 } 从 'y-indexeddb'
常数 ydoc公司 = 新的 年 . 文件 ( )
//这允许您立即获取(缓存的)文档数据
常数 索引bProvider = 新的 索引ddb持久性 ( 'count-demo' , ydoc公司 )
索引bProvider . 同步时 . 然后 ( ( ) => {
慰问 . 日志 ( '已从索引数据库加载数据' )
} )
//将客户端与y-webrtc提供程序同步。
常数 webrtc提供商 = 新的 Webrtc提供商 ( 'count-demo' , ydoc公司 )
//将客户端与y-websocket提供程序同步
常数 网络套接字提供商 = 新的 Websocket提供程序 (
' wss://demos.yjs.dev版 ' , 'count-demo' , ydoc公司
)
//产生和的数字数组
常数 亚雷 = ydoc公司 . 获取数组 ( “计数” )
//观察总和的变化
亚雷 . 观察 ( 事件 => {
//数据更改时打印更新
慰问 . 日志 ( '新总和£º' + 亚雷 . 到阵列 ( ) . 减少 ( ( 一 , b条 ) => 一 + b条 ) )
} )
//总和加1
亚雷 . 推 ( [ 1 ] ) //=>“新总和:1”
进口 * 作为 年 从 “是的”
Y.阵列
const-yarray=新Y.Array()
在以下位置插入内容 指数 。请注意,内容是一个元素数组。 即。 数组.insert(0,[1]) 拼接列表并在处插入1 位置0。 检索一系列内容 将此YArray的内容复制到新数组。 将此YArray的内容复制到一个新的Array中。 它转换所有子类型 使用它们的 到JSON 方法。 返回一个YArray迭代器,其中包含数组中每个索引的值。 for(让yarray的值){..} 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型已修改。 如果在事件侦听器中修改了此类型, 当前事件侦听器返回后,将再次调用事件侦听器。 删除 观察 此类型的事件侦听器。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型或其任何子级都已修改。 如果修改了此类型 在事件侦听器中,事件侦听器将在当前 事件侦听器返回。 事件侦听器接收自己创建的所有事件 或其任何子公司。 删除 观察深度 此类型的事件侦听器。
父级:Y.AbstractType | null
插入(索引:数字,内容:数组<object|boolean|Array |string|null|Uint8Array |Y.Type>)
push(数组<Object|boolean|Array |string|number|null|Uint8Array |Y.Type>)
unshift(Array<Object | boolean | Array | string | number | null | Uint8Array | Y.Type>)
删除(索引:数字,长度:数字)
get(索引:数字)
slice(开始:number,结束:number):Array<Object | boolean | Array | string | number | null | Uint8Array | Y.Type>
长度:数字
forEach(函数(值:object | boolean | Array | string | number | null | Uint8Array | Y.Type, 索引:数字,数组:Y.array))
map(函数(T,number,YArray):M):数组<M>
toArray():数组<object|boolean|Array | string | number | null | Uint8Array | Y.Type>
toJSON():数组<Object|boolean|Array|string|number|null>
[符号.迭代器]
observe(函数(YArrayEvent,事务):void)
unobserve(函数(YArrayEvent,事务):void)
observeDeep(函数(数组<YEvent>,事务):void)
unobserveDeep(函数(数组<YEvent>,事务):void)
Y.地图
const ymap=新Y.Map()
键/值对的总数。 删除此YMap中的所有元素。 将此类型克隆到一个新的Yjs类型中。 复制 [键,值] 这对Y映射到一个新对象。 它 使用它们的 到JSON 方法。 对每个键值对执行一次提供的函数。 返回的迭代器 [键,值] 对。 for(让ymap的[key,value]){..} 返回的迭代器 [键,值] 对。 返回所有值的迭代器。 返回所有键的迭代器。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型已修改。 在该类型在事件监听器中被修改的情况下, 当前事件侦听器返回后,将再次调用事件侦听器。 删除 观察 此类型的事件侦听器。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型或其任何子级都已修改。 如果修改了此类型 在事件监听器中,将在当前事件监听器之后再次调用事件监听器 事件侦听器返回。 事件侦听器接收自己创建的所有事件 或其任何子公司。 删除 观察深度 此类型的事件侦听器。
父级:Y.AbstractType | null
大小:数字
get(key:string):object | boolean | string | number | null | Uint8Array | Y.Type
set(键:string,值:object | boolean | string | number | null | Uint8Array | Y.Type)
删除(键:字符串)
has(key:string):boolean
get(索引:数字)
清除()
克隆():Y.Map
toJSON():Object<string,Object|boolean|Array|string|number|null|Uint8Array>
forEach(函数(值:object | boolean | Array | string | number | null | Uint8Array | Y.Type, 键:字符串,映射:Y.map))
[符号.迭代器]
条目()
值()
按键()
observe(函数(YMapEvent,Transaction):void)
unobserve(函数(YMapEvent,事务):void)
observeDeep(函数(数组<YEvent>,事务):void)
unobserveDeep(函数(数组<YEvent>,事务):void)
Y.文本
const ytext=新Y.Text()
在处插入字符串 指数 并为其指定格式属性。 ytext.insert(0,'粗体文本',{粗体:true}) 将格式属性指定给文本中的范围 请参见 套筒三角洲 可以设置选项以防止删除结束newLines,默认值为true。 ytext.applyDelta(delta,{sanitize:false}) 将此类型(无格式选项)转换为字符串。 请参见 toString(字符串) 将此类型转换为 套筒三角洲 将事件侦听器添加到此类型,每次都会同步调用 此类型已修改。 如果在事件侦听器中修改了此类型, 当前事件侦听器返回后,将再次调用事件侦听器。 删除 观察 此类型的事件侦听器。 将事件侦听器添加到此类型,每次都会同步调用 此类型或其任何子级都已修改。 如果修改了此类型 在事件侦听器中,事件侦听器将在当前 事件侦听器返回。 事件侦听器接收自己创建的所有事件 或其任何子公司。 删除 观察深度 此类型的事件侦听器。
父级:Y.AbstractType | null
插入(索引:数字,内容:字符串,[formattingAttributes:Object<string,string>])
删除(索引:数字,长度:数字)
格式(索引:数字,长度:数字,格式属性:对象<string,string>)
applyDelta(delta:增量,opts:对象<string,any>)
长度:数字
toString():字符串
toJSON():字符串
toDelta():增量
observe(函数(YTextEvent,事务):void)
unobserve(函数(YTextEvent,事务):void)
observeDeep(函数(数组<YEvent>,事务):void)
unobserveDeep(函数(数组<YEvent>,事务):void)
Y.Xml片段
constyxml=新Y.XmlFragment()
检索一系列内容 将此类型克隆为新的Yjs类型。 将子项复制到新数组。 将此类型和所有子项转换为新的DOM元素。 获取所有子体的XML序列化。 请参见 toString(字符串) . 创建一个遍历子对象的Iterable。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型已修改。 如果在事件侦听器中修改了此类型, 当前事件侦听器返回后,将再次调用事件侦听器。 删除 观察 此类型的事件侦听器。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型或其任何子级都已修改。 如果修改了此类型 在事件侦听器中,事件侦听器将在当前 事件侦听器返回。 事件侦听器接收自己创建的所有事件 或其任何子公司。 删除 观察深度 此类型的事件侦听器。
父级:Y.AbstractType | null
firstChild:Y.XmlElement | Y.Xml文本|空
插入(索引:数字,内容:数组<Y.XmlElement | Y.Xml文本>)
删除(索引:数字,长度:数字)
get(索引:数字)
slice(start:number,end:number):数组<Y.XmlElement | Y.Xml文本>
长度:数字
克隆():Y.XmlFragment
toArray():数组<Y.XmlElement | Y.XmlText>
toDOM():文档片段
toString():字符串
toJSON():字符串
createTreeWalker(filter:function(AbstractType<any>):boolean):可迭代
observe(函数(YXmlEvent,事务):void)
unobserve(函数(YXmlEvent,事务):void)
observeDeep(函数(数组<YEvent>,事务):void)
unobserveDeep(函数(数组<YEvent>,事务):void)
Y.Xml元素
constyxml=新Y.XmlElement()
检索第i个元素。 检索一系列内容 将此类型克隆为新的Yjs类型。 将子项复制到一个新的数组中。 将此类型和所有子项转换为新的DOM元素。 获取所有子体的XML序列化。 请参见 toString(字符串) . 将事件侦听器添加到此类型,该类型将每隔 修改此类型的时间。 如果在事件中修改了此类型 监听器,事件监听器将在当前事件之后再次调用 侦听器返回。 删除 观察 此类型的事件侦听器。 将事件侦听器添加到此类型,每次都会同步调用该类型 此类型或其任何子级都已修改。 如果修改了此类型 在事件侦听器中,事件侦听器将在当前 事件侦听器返回。 事件侦听器接收自己创建的所有事件 或其任何子公司。 删除 观察深度 此类型的事件侦听器。
父项:Y.AbstractType | null
firstChild:Y.XmlElement | Y.Xml文本|空
nextSibling:Y.XmlElement | Y.Xml文本|空
prevSibling:Y.XmlElement | Y.Xml文本| null
insert(索引:数字,内容:数组<Y.XmlElement|Y.XmlText>)
删除(索引:数字,长度:数字)
get(索引:数字)
长度:数字
setAttribute(属性名称:string,属性值:string)
removeAttribute(属性名称:字符串)
getAttribute(attributeName:string):string
getAttributes():对象<string,string>
get(i:number):Y.XmlElement | Y.XmlText
slice(start:number,end:number):数组<Y.XmlElement | Y.Xml文本>
克隆():Y.XmlElement
toArray():数组<Y.XmlElement|Y.Xml文本>
toDOM():元素
toString():字符串
toJSON():字符串
observe(函数(YXmlEvent,事务):void)
unobserve(函数(YXmlEvent,事务):void)
observeDeep(函数(数组<YEvent>,事务):void)
unobserveDeep(函数(数组<YEvent>,事务):void)
常数 文件 = 新的 年 . 文件 ( )
标识此客户端的唯一id。 (只读) 此文档实例上是否启用了垃圾收集。 设置`doc.gc=false` 以便禁用gc并能够恢复旧内容。 请参见 https://github.com/yjs/yjs#yjs -crdt算法 有关Yjs中gc的更多信息。 共享文档上的每个更改都发生在事务中。 观察员呼叫和 这个 更新 在每个事务之后调用事件。 你应该 捆 更改为单个事务以减少事件量 电话。 即。 doc.transact(()=>{yarray.insert(..);ymap.set(..)}) 触发单个更改事件。 您可以指定一个可选的 起源 存储在上的参数 交易.来源 和 on('update',(update,origin)=>..) . 不推荐:建议直接对共享类型调用toJSON。 将整个文档转换为js对象,递归遍历每个yjs 类型。 不记录尚未定义的类型(使用 ydoc.getType(..) ). 定义共享类型。 定义共享的Y数组类型。 等于 y.get(字符串,y.Array) . 定义共享的Y映射类型。 相当于 y.get(字符串,y.Map) . 定义共享的Y文本类型。 等于 y.get(字符串,y.Text) . 定义共享的Y.XmlElement类型。 相当于 y.get(字符串,y.XmlElement) . 定义共享的Y.XmlFragment类型。 等于 y.get(字符串,y.XmlFragment) . 在共享类型上注册事件侦听器 从共享类型中注销事件侦听器
客户端ID
气相色谱法
transact(函数(Transaction):void[,origin:any])
toJSON():任何
get(字符串,Y.[TypeClass]):[Type]
getArray(字符串):Y.Array
getMap(字符串):Y.Map
getText(字符串):Y.Text
getXmlElement(string,string):Y.XmlEletion
getXmlFragment(字符串):Y.XmlFragrament
on(字符串,函数)
关闭(字符串,函数)
收听文档更新。 文件更新必须发送给所有其他人 同龄人。 您可以按任意顺序多次应用文档更新。 使用`updateV2` 接收V2事件。 在每个事务之前发出。 每次交易后发出。 事务可以嵌套(例如,当一个事务中的事件调用另一个 交易)。 在第一个事务之前发出。 清除最后一个事务后发出。
on('update',函数(updateMessage:Uint8Array,origin:any,Y.Doc):void)
on('beforeTransaction',函数(Y.Transaction,Y.Doc):void)
on('afterTransaction',函数(Y.Transaction,Y.Doc):void)
on('beforeAllTransactions',函数(Y.Doc):void)
on('afterAllTransactions',函数(Y.Doc,数组<Y.Transaction>):void)
常数 文档1 = 新的 年 . 文件 ( )
常数 文档2 = 新的 年 . 文件 ( )
文档1 . 在 ( '更新' , 更新 => {
年 . 应用更新 ( 文档2 , 更新 )
} )
文档2 . 在 ( '更新' , 更新 => {
年 . 应用程序更新 ( 文档1 , 更新 )
} )
//所有更改也应用于其他文档
文档1 . 获取数组 ( “myarray” ) . 插入 ( 0 , [ “你好,doc2,你明白了吗?” ] )
文档2 . 获取数组 ( “myarray” ) . 得到 ( 0 ) //=>“你好,doc2,你明白了吗?”
常数 状态1 = 年 . 将状态编码为更新 ( ydoc1型 )
常数 状态2 = 年 . 将状态编码为更新 ( ydoc2型 )
年 . 应用更新 ( ydoc1公司 , 状态2 )
年 . 应用更新 ( ydoc2型 , 状态1 )
常数 状态矢量1 = 年 . 编码状态向量 ( ydoc1公司 )
常数 状态矢量2 = 年 . 编码状态向量 ( ydoc2型 )
常数 差异1 = 年 . 将状态编码为更新 ( ydoc1公司 , 状态矢量2 )
常数 差异2 = 年 . 将状态编码为更新 ( ydoc2型 , 状态矢量1 )
年 . 应用更新 ( ydoc1公司 , 差异2 )
年 . 应用更新 ( ydoc2型 , 差异1 )
//将当前状态编码为二进制缓冲区
让 当前状态1 = 年 . 将状态编码为更新 ( ydoc1公司 )
让 当前状态2 = 年 . 将状态编码为更新 ( ydoc2型 )
//现在,我们可以继续使用状态向量同步客户端,而无需使用Y.Doc
ydoc1公司 . 破坏 ( )
ydoc2型 . 破坏 ( )
常数 状态矢量1 = 年 . 编码状态矢量源更新 ( 当前状态1 )
常数 状态矢量2 = 年 . 编码状态矢量源更新 ( 当前状态2 )
常数 差异1 = 年 . 差异更新 ( 当前状态1 , 状态矢量2 )
常数 差异2 = 年 . 差异更新 ( 当前状态2 , 状态矢量1 )
//同步客户端
当前状态1 = 年 . 合并更新 ( [ 当前状态1 , 差异2 ] )
当前状态2 = 年 . 合并更新 ( [ 当前状态2 , 差异1 ] )
常数 ydoc公司 = 新的 年 . 文件 ( )
//执行一些更改。。
ydoc公司 . 获取文本 ( ) . 插入 ( 0 , “你好,世界” )
常数 更新 = 年 . 将状态编码为更新 ( ydoc公司 )
//以下更新包含加扰数据
常数 模糊更新 = 年 . 模糊更新 ( 更新 )
常数 ydoc2型 = 新的 年 . 文件 ( )
年 . 应用更新 ( ydoc2型 , 模糊更新 )
ydoc2型 . 获取文本 ( ) . toString(字符串) ( ) // => "00000000000"
对共享文档应用文档更新。 您可以选择指定 交易来源 将存储在 交易.来源 和 ydoc.on('update',(update,origin)=>..) . 将文档状态编码为可应用于 远程文档。 (可选)指定目标状态向量以仅写入 更新消息的差异。 计算状态向量并将其编码为Uint8Array。 删除时将多个文档更新合并为单个文档更新 重复信息。 合并文档更新始终小于 由于压缩编码而进行的单独更新。 从文档更新计算状态向量并将其编码到Uint8Array。 将缺少的差异编码为另一条更新消息。 此功能有效 类似于 Y.encodeStateAsUpdate(ydoc,stateVector) 但奏效了 而不是更新。 将V1更新格式转换为V2更新格式。 将V2更新格式转换为V1更新格式。
Y.applyUpdate(Y.Doc,更新:Uint8Array,[transactionOrigin:any])
Y.encodeStateAsUpdate(Y.Doc,[encodedTargetStateVector:Uint8Array]):Uint8数组
Y.encodeStateVector(Y.Doc):Uint8Array
Y.mergeUpdates(阵列<Uint8Array>)
Y.encodeStateVectorFromUpdate(Uint8Array):Uint8Array
Y.diffUpdate(更新:Uint8Array,状态向量:Uint9Array):Uint8数组
将更新格式V1转换为V2
将更新格式V2转换为V1
常数 relPos(相对位置) = 年 . 从类型索引创建相对位置 ( y文本 , 2 )
常数 销售时点情报系统 = 年 . 从相对位置创建绝对位置 ( relPos(相对位置) , 文件 )
销售时点情报系统 . 类型 === y文本 //=>真
销售时点情报系统 . 指数 === 2 //=>真
常数 relPos(相对位置) = 年 . 从类型索引创建相对位置 ( y文本 , 2 )
常数 编码RelPos = JSON格式 . 字符串 ( relPos(相对位置) )
//将encodedRelPos发送到远程客户端。。
常数 解析的RelPos = JSON格式 . 解析 ( 编码RelPos )
常数 销售时点情报系统 = 年 . 从相对位置创建绝对位置 ( 解析的RelPos , 远程文档 )
销售时点情报系统 . 类型 === 远程文本 //=>真
销售时点情报系统 . 指数 === 2 //=>真
常数 relPos(相对位置) = 年 . 从类型索引创建相对位置 ( y文本 , 2 )
常数 编码器返回位置 = 年 . 编码相对位置 ( relPos(相对位置) )
//将encodedRelPos发送到远程客户端。。
常数 解析的RelPos = 年 . 解码相对位置 ( 编码RelPos )
常数 销售时点情报系统 = 年 . 从相对位置创建绝对位置 ( 解析的RelPos , 远程文档 )
销售时点情报系统 . 类型 === 远程文本 //=>真
销售时点情报系统 . 指数 === 2 //=>真
创建固定到任何序列中第i个元素的相对位置 共享类型(如果 关联>=0 ). 默认情况下,该职位关联 带有指定索引位置后面的字符。 如果 关联<0 ,则相对位置与角色关联 在指定的索引位置之前。 从相对位置创建绝对位置。 如果相对位置 无法引用,或类型被删除,则结果为null。 对Uint8Array的相对位置进行编码。 二进制数据是首选 文档更新的编码格式。 如果您喜欢JSON编码,可以 只需JSON.stringify/JSON.parse相对位置即可。 将二进制编码的相对位置解码为RelativePosition对象。
Y.createRelativePositionFromTypeIndex(类型:Uint8Array | Y.type,索引:数字 [,关联=0])
Y.createAbsolutePositionFromRelativePosition(相对位置,Y.Doc): {type:Y.AbstractType,index:number,assoc:number}|null
Y.encodeRelativePosition(相对位置):Uint8Array
Y.decodeRelativePosition(Uint8Array):相对位置
常数 y文本 = 文件 . 获取文本 ( “文本” )
常数 撤消管理器 = 新的 年 . 撤消管理器 ( y文本 )
y文本 . 插入 ( 0 , “abc” )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) // => ''
撤消管理器 . 重做 ( )
y文本 . toString(字符串) ( ) //=>“abc”
接受单个类型作为范围或类型数组。 注册当 堆叠项 已添加到 undo或redo-stack。 注册当现有 堆叠项 已更新。 当“captureInterval”中发生两个更改时,就会发生这种情况。 注册当 堆叠项 从弹出 undo或redo-stack。 注册在撤消和/或重做堆栈被清除时调用的事件。
构造函数(范围:Y.AbstractType |数组<Y.AbtractType> [,{captureTimeout:number,trackedOrigins:Set<any>,deleteFilter:function(item):boolean}])
撤消()
重做()
停止捕获()
on('stack-item-added',{stackItem:{meta:Map<any,any>},type:'undo' |“重做”})
on('stack-item-updated',{stackItem:{meta:Map<any,any>},type:'undo' |“重做”})
on('stack-item-popped',{stackItem:{meta:Map<any,any>},类型:“undo” |“重做”})
on('stack-cleared',{undoStackCleared:布尔值,redoStackclered:布尔})
//无需停止捕获
y文本 . 插入 ( 0 , “a” )
y文本 . 插入 ( 1 , “b” )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“”(注意删除了“ab”)
//带stopCapturing
y文本 . 插入 ( 0 , “a” )
撤消管理器 . 停止捕获 ( )
y文本 . 插入 ( 0 , “b” )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“a”(注意,只删除了“b”)
. The
班 自定义绑定 { }
常数 y文本 = 文件 . 获取文本 ( “文本” )
常数 撤消管理器 = 新的 年 . 撤消管理器 ( y文本 , {
追踪来源 : 新的 设置 ( [ 42 , 自定义绑定 ] )
} )
y文本 . 插入 ( 0 , “abc” )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“abc”(不跟踪,因为原点为“null”且不是零件
//(共`trackedTransactionOrigins`)
电子文本 . 删除 ( 0 , 三 ) //恢复更改
文件 . 办理 ( ( ) => {
y文本 . 插入 ( 0 , “abc” )
} , 42 )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“”(由于origin是“trackedTransactionorigins`”的实例,因此被跟踪)
文件 . 办理 ( ( ) => {
y文本 . 插入 ( 0 , “abc” )
} , 41 )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“abc”(未跟踪,因为41不是
//`trackedTransactionorigins`)
y文本 . 删除 ( 0 , 三 ) //恢复更改
文件 . 办理 ( ( ) => {
y文本 . 插入 ( 0 , “abc” )
} , 新的 自定义绑定 ( ) )
撤消管理器 . 解开 ( )
y文本 . toString(字符串) ( ) //=>“”(由于原点是“CustomBinding”且
//`CustomBinding`位于`trackedTransactionorigins`中)
常数 y文本 = 文件 . 获取文本 ( “文本” )
常数 撤消管理器 = 新的 年 . 撤消管理器 ( y文本 , {
跟踪来源 : 新的 设置 ( [ 42 , 自定义绑定 ] )
} )
撤消管理器 . 在 ( '堆叠项已添加' , 事件 => {
//将当前光标位置保存在堆栈项上
事件 . 堆栈项 . 元 . 设置 ( '光标位置' , 获取相对光标位置 ( ) )
} )
撤消管理器 . 在 ( '堆叠项已停止' , 事件 => {
//恢复堆栈项上的当前光标位置
恢复光标位置 ( 事件 . 堆栈项 . 元 . 得到 ( '光标位置' ) )
} )
如果用户按顺序插入元素,则结构将合并为 单个结构。 例如。 text.insert(0,'a'),text.inset(1,'b'); 是 首先表示为两个结构( [{id:{客户端,时钟:0},内容:“a”},{id:}客户端,时间:1},content:“b”} )然后合并成一个 结构: [{id:{客户端,时钟:0},内容:'ab'}] . 当包含内容的结构(例如。 项目字符串 )删除,则 结构将替换为 项目已删除 不包含内容的 不再。 删除类型时,所有子元素都将转换为 GC公司 结构。 一 GC公司 struct只表示存在一个struct,并且该struct已被删除。 GC公司 结构始终可以与其他结构合并 GC公司 如果id是 相邻。