阅读 192

Slate.js 之 Operation 概述

Slate.js 介绍

Slate 是一个 L1 级的富文本编辑器框架,其架构分为四个部分:核心逻辑层slate、视图层slate-react、历史操作层slate-history以及用于复制粘贴外部内容的 helper slate-hyperscript

image.png

本文的主题是 slate 层中的一个概念,Operation。

Operation

Operation 是 Slate 中进行变换的粒度最小的原子操作,所有的高级变换(Transforms API)归根结底其实都只是一个或者多个 Operation 的封装打包。

Operation 能够帮助我们实现历史操作(撤销/重做)、协同编辑等功能。如此重要的内容,却缺乏官方的 API 文档作为参考,由是撰写本文。

规范

Opertaion 原子操作,它是一个对象,该对象必须包含属性 type

type 的取值为以下 Slate 中支持的总共 9 种 Operations。

image.png

其中 insert_noderemove_nodeinsert_textremove_textmerge_nodesplit_node 三对操作互为逆运算,而余下的三者的逆运算为自身。

逆运算的意思是,两个 Operation 执行的操作得到的效果是完全相反的。

互为逆操作

举个例子,我想“插入文本”——在 { path:[0], offset: 0} 这个 Point 插入一个字符串 "hello"。

e.apply(     {type: 'insert_text', path: [0], offset: 0, "hello"} ) 复制代码

按照对于上图的理解,将 insert_text 改成逆操作 remove_text,以下代码可撤销掉“插入文本”。

e.apply(     {type: 'remove_text', path: [0], offset: 0, "hello"} ) 复制代码

Slate 本身提供了 Operation.inverse(op) 的方法。输入、输出均是 Operation,可用它替我们撤销“插入文本”。

e.apply(     Operation.inverse(         {type: 'insert_text', path: [0], offset: 0, "hello"}     ) ) 复制代码

源码中,Operation.inverse(op) 对于 typeinsert_text 的情形,所做的事情也不过是将 typeremove_text 替换,然后返回这个 Operation 出来。

逆运算为自身

伪原创工具 SEO网站优化  https://www.237it.com/ 

对于逆运算为自身的情况,move_nodeset_nodeset_selection

// 移动节点 e.apply(     {type: 'move_node', path: [1], newPath: [0]} ) // 逆运算如下 e.apply(     {type: 'move_node', path: [0], newPath: [1]} ) // 设置节点属性 e.apply(     {type: 'set_node', path: [0], properties: {lineHeight: 1.75}, newProperties: {lineHeight: 2}}  ) // 逆运算如下 e.apply(     {type: 'set_node', path: [0], properties: {lineHeight: 2}, newProperties: {lineHeight: 1.75}} )      // 设置选区属性 e.apply(     {type: 'set_selection', properties: null, newProperties: {bold: true}}  ) // 逆运算如下 e.apply(     {type: 'set_selection',  properties: {bold: true}, newProperties: null}  ) 复制代码

move_nodeset_nodeset_selection 三者有一个共同的特点,就是 Operation 中含有一个 X,同时又存在一个 newX。当他们取逆运算的时候,只需要将 XnewX 对调即可。

同样,你也可以并且应该使用 Operation.inverse(op) 更高效地实现逆运算。

e.apply(     Operation.inverse(         {type: 'set_selection', properties: null, newProperties: {bold: true}}      ) ) 复制代码

上述仅描述 Operation 作为一个接口时体现的特性,具体涉及到在 editor 中应用某个操作的逻辑,可以参考transform。

应用

历史操作

由于 Operation 支持互逆操作的特性,因此可以将它们以数组的形式存储起来,用来保存历史操作。

slate-history 中提供的 HistoryEditor 包装了两个数组(undoredo) 到 editor 实例上。

e.history = {undo: [], redo: []} 复制代码

协同编辑

Slate 的协同是基于交换可复制数据类型(CRDT, Commutative Replicated Data Types),目前的技术包括slate-collaborative 以及 Yjs。

Operation 提供了最小粒度的原子操作,而至于操作之间如何优雅地(即保留作者意图的信息地)合并在一起,由这篇译文讲解算法相关的逻辑。


作者:swanf
链接:https://juejin.cn/post/7034480408888770567


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐