【辣眼慎入】学习 结合Yjs制作编辑器 有感(一)

4,364 阅读6分钟

最近在线协同编辑类的产品都非常火,它的优点就是可以在工作团队内多人协作时高效、准确地管理共享的文档和数据。

(用赖死不活的语气写这篇文章主要是觉得这个东西对我来说有点陌生,但是又 a little 感兴趣,帮助自己梳理知识点的同时想和大家交流沟通碰撞火花,轻喷轻喷)

CRDT(Conflict-free    replicated    data    type)

CRDT是一个术语。单词之间空了四个空格是为了让大家从纯英文的角度去理解这个词的概念:冲突    无    复制    数据    类型。

无冲突复制数据类型。结合开头所说的多人在线协作,这个东西大概就是多个终端之间修改来修改去,但是不产生冲突的数据类型。

但是我们第一步记住:CRDT是个数据类型,多终端修改来修改去不会起冲突的数据类型。

当我们在多端协作时,为了避免冲突,有一个执行合并先后顺序的算法,它的存在可以避免改动后多端内容不一致。在CRDT算法中,数据合并的顺序不影响内容最终一致性(这里也会涉及到一些向量的概念,也会涉及到一些数学运算法:交换律、结合律、幂等性)。

CRDT算法之前,也有一些其他的算法来解决协同类的问题,但是它们也会有一些缺点:

OT算法:递归求解算法,计算过于密集。
AST算法:多个时间戳,回溯到最近的无冲突版本处理冲突。

CRDT过程:

首先清楚以下几个元素:

S0(初始状态)

S(状态State):可以理解为副本。

q(query):查询操作,仅查询本地副本。

u(update):更新操作,先尝试进行本地副本更新,若更新成功则将本地更新同步至远端副本。这里是两步,第一步是更新本地副本,第二步是同步至远端副本

m(merge):update在远端副本的合并操作。

S0(初始状态)通过交换律和结合律等进行update和merge,变成S(状态State)。

适用场景:

数据同步、多端协同。

CRDT有两种类型:基于状态类型  和  基于操作类型

两种类型:

基于状态类型:各个节点之间的数据直接合并,最终合并到同一个状态。
基于操作类型:每个数据的改动通知给其他节点,节点知道了所有的数据操作,最终合并到同一个状态。

查看更多这方面的知识点,请去维基百科:CRDT

好,先浅尝辄止,看下一个点。

Yjs

关于Yjs的介绍,我去看了官方文档:


我确实不太懂...   模块化构建块??!!bulls***

没关系,先把相关东西下下来,跑起来,控制台多打印打印就好了。

附上Yjs的官方文档:点我

1. Yjs-demo下载

传送门:Yjs-demo

然后冲向README.md!!

2. 跑起来

这个npm install的时间还挺久的,等吧。

然后npm start出来了这个。嗯,界面还挺丑的。anyway~不重要,可能这个团队不是靠脸吃饭的吧,继续乱点吧冲鸭!!

第一个:ProseMirror Binding(ProseMirror是富文本编辑器框架,mirror是镜子,那这个反正又跟什么镜像啊复制啊这种东西有关,binding绑定,反正应该就是绑定框架吧)

出来了一个富文本编辑器。

既然是多人协作的编辑器,那就再打开另一个会话框然后测试测试吧。果然,协作是可以协作的。

行了,去瞅第二个ProseMirror Binding with Version History(带有历史版本记录的富文本编辑器??反正这块有历史版本记录)

好,看第三个 

Yjs + Dat Protocol Demo (with offline support and p2p sync using Dat)

Yjs + 数据协议演示(离线支持和直接同步使用数据)。个人觉得p2p翻译成“直接”比较好。

第四个

ProseMirror-Atlaskit Binding(Atlaskit感觉是个编辑器里的什么组件)

好像中文翻译过来和第三个一样?但是富文本编辑器里的功能变多了。而且界面更加成熟好看点。


然后这页的右上角有一个按钮,控制连接(connect)和断开(disconnect)的按钮。当我点击断开(disconnect)的时候,我发现编辑器里的内容不会同步了。


(憨憨微笑)

第五个

Quill Binding(查了下,这个Quill也是个编辑器,好像很出名)

第五个和第四个差不多

噢,我现在懂了,这几个链接应该都是用Yjs框架做的编辑器吧。而且我发现除了第三个和第八个链接没有断开(disconnect)按钮之外,其他的几个链接里都有这个按钮。

但是,如果实际做项目,quill在数据兼容上可能存在较大问题(新的数据结构不容易兼容老的数据结构)。

它的核心类(Core Class)有:editor、selection(选区处理)、module(模块管理)、quill、emitter(事件处理:一个典型的pubSub模式)。

第六个

Monaco Binding


嗯,黑色的一大片,还挺酷炫的。我的直觉告诉我,这是个代码编辑器协同工具???

anyway,往下走第七个 

CodeMirror Binding(code .... mirror...估计也是代码协同类的

最后一个了!!!

TipTap Binding(这个名字.....还挺霸气的,翻译过来感觉像是“至尊编辑器”之类的??)
好,那我们瞅瞅这个至尊编辑器。

牛逼了,这个编辑器的工具栏竟然都是文字而不是小图标.........

好任性.........极简风吗??!!

找到了tiptap传送门~

TipTap的定位就是:无样式编辑器框架,而不是传统的编辑器应用。

它是一款专为vue.js 打造,设计优雅、体验流畅的现代富文本编辑器,且TipTap提供了大量编辑器的功能,但是拓展性没有Slate好。

Slate-js的github地址

对比

拓展性:Quill = ProseMirror > TipTap

Vue友好度:TipTap > Quill = ProseMirror

好了,链接点击完毕——

所以.....我下载的这个demos是什么???

算了,就暂定是用Yjs做的几种不同的编辑器吧。

回到模块化构建块****modular building blocks.........

模块化构建块(modular building blocks)

刚刚提到,它的本质是一个数据类型。它应该是跟block(块)有关的数据类型。然后是遵循一个有规律有公式的数学约束的(我猜测的,不要入戏太深)。

更进一步说:在一般的基于block的编辑器里面, 公认为一个最细粒度的完整数据单元:比如映射为dom tree上的div。那么在编辑器里,这个block就是一行或者一个字符??

突然,灵光一闪,我觉得它就是建房子时的砖头🧱

好了,下一个点。

编辑器应用/编辑器框架

现在大部分富文本编辑器(特别是老款)还是编辑器应用的思路去做的,而ProseMirror的设计思路定位的就是编辑器框架,而不是编辑器应用。

编辑器框架意味着我们能在它的基础上开发出适用于自己的富文本编辑器应用。其中,最核心的思想是:MVC分层和基于单向数据流的应用架构Flux。

1. Flux架构入门教程

点我

2. Flux单向数据流

在Flux中,包含了四种元素:

  1. Action - 动作消息
  2. View - 外部交互
  3. Store - 数据存储/动作处理
  4. Dispatcher - 转发消息