- Published on
Delta 格式的本质详解
- Authors
- Name
- Alex
- @adams6688
Delta 格式的本质是什么?
🧠 Delta 格式的本质详解
🌱 1. Delta 格式的起源与设计理念
Delta
格式由 Quill.js 编辑器引入,旨在以 面向操作 的方式描述富文本内容和其变更。 其核心目标是:
- 📝 简洁地描述内容和格式:避免复杂的 DOM 操作和数据结构。
- 🔄 高效地同步和回放变更:便于协作编辑、撤销/重做、历史记录管理。
- 📡 便于网络同步:以最小的变更单位进行数据传输,适用于 CRDT 和 OT 算法。
🔍 本质:Delta 是一种面向操作的文档变更描述格式
Delta ≠ 文本内容,它并不直接描述完整的文本,而是以 操作序列 描述文本内容及其变更。 每次编辑(插入、删除、样式变更)都会生成新的 Delta
操作,描述 从旧内容到新内容 的差异。
📑 2. Delta 格式的数据结构
Delta
的核心数据结构是一个有序的操作数组(Operations Array),每个操作由以下三个核心类型之一组成:
操作类型 | 作用 | 关键字段 | 示例 |
---|---|---|---|
insert | 在指定位置插入文本或嵌入对象 | insert 、attributes | {"insert": "Hello"} |
delete | 删除指定长度的文本 | delete | {"delete": 5} |
retain | 跳过指定长度的文本(通常用于修改样式) | retain 、attributes | {"retain": 6, "attributes": {"bold": true}} |
🔧 2.1 操作格式
每个操作是一个 JSON 对象,具有以下字段:
字段 | 类型 | 含义 | 示例 |
---|---|---|---|
insert | string /object | 插入的文本或嵌入内容(如图片、视频)。 | { "insert": "Hello" } |
delete | number | 删除指定长度的字符。 | { "delete": 5 } |
retain | number | 跳过指定长度的字符(通常用于样式变更)。 | { "retain": 6 } |
attributes | object | 可选,描述文本或嵌入内容的样式和属性。 | { "bold": true } |
📜 2.2 示例:构建文本
我们通过 Delta
构建以下富文本: 文本内容:Hello World
样式:Hello
为普通文本,World
加粗。
Delta 表示:
[
{ "insert": "Hello " },
{ "insert": "World", "attributes": { "bold": true } }
]
解读:
- 插入
Hello
(无样式)。 - 插入
World
并加粗。
等效文本: Hello **World**
🔄 3. Delta 格式的工作机制
🎯 3.1 增量变更描述
Delta
记录的并非完整的文档状态,而是通过操作数组描述从 上一个状态到当前状态 的 变更过程。
例如,文本从 Hello World
修改为 Hello Flutter
:
原始文本:
[{ "insert": "Hello World" }]
修改过程:
- 删除
World
:
[{ "retain": 6 }, { "delete": 5 }]
- 插入
Flutter
:
[{ "retain": 6 }, { "insert": "Flutter" }]
合并后的完整 Delta:
[
{ "retain": 6 },
{ "delete": 5 },
{ "insert": "Flutter" }
]
最终内容: Hello Flutter
🔍 3.2 样式变更
假设我们要将 Flutter
设置为加粗和红色:
[
{ "retain": 6 },
{ "retain": 7, "attributes": { "bold": true, "color": "red" } }
]
解释:
- retain 6:跳过前 6 个字符(
Hello
)。 - retain 7 + attributes:为接下来的 7 个字符(
Flutter
)加粗并设为红色。
🔄 3.3 合并与压缩
Delta
支持相同类型的连续操作进行合并,减少数据膨胀。
🆘 未优化:
[
{ "insert": "Hello " },
{ "insert": "World" }
]
✅ 优化后:
[
{ "insert": "Hello World" }
]
这种合并通常由 Delta.compose()
自动完成。
🌐 4. Delta 格式的优势
⚡ 优势 | 🚨 解释 |
---|---|
🛠️ 结构简单 | 基于数组和 JSON 格式,易于理解和实现。 |
🔄 便于协作编辑 | 支持 CRDT 和 OT 算法,实现多人协作。 |
🚀 网络高效 | 只需传输增量变更,而非整个文档内容。 |
🧠 撤销/重做简单 | 每个 Delta 操作自带可逆性,撤销和重做基于操作序列。 |
🔍 格式与内容解耦 | 内容由 insert 提供,样式由 attributes 管理,互不干扰。 |
⚠️ 5. Delta 格式的局限性
尽管 Delta 格式具备诸多优点,但在以下场景中可能存在性能和复杂性问题:
📈 5.1 数据膨胀
- 频繁编辑、撤销和样式变更会导致操作数组无限增长。
- 解决方案:定期合并相同类型的操作,使用
Delta.transform()
和Delta.compose()
。
⚠️ 5.2 嵌套结构支持有限
Delta
是线性数据结构,无法直接表达复杂的嵌套关系(如表格、树状列表)。- 解决方案:AppFlowy 结合 Node Tree 实现层次结构。
🔄 5.3 大文本性能
- 处理大型文档时,
Delta
的性能可能下降,尤其是基于光标的样式修改。 - 解决方案:引入分块存储和懒加载策略。
🔧 6. Delta 的关键 API 方法
🛠️ 6.1 compose():合并两个 Delta
Delta.compose()
将当前 Delta
与另一个 Delta
合并,生成新版本。
示例:
const delta1 = new Delta().insert('Hello');
const delta2 = new Delta().insert(' World');
const merged = delta1.compose(delta2);
console.log(merged);
// => [{ insert: "Hello World" }]
🛠️ 6.2 transform():变换 Delta
在协作编辑中,Delta.transform()
用于在并发操作下调整光标位置和变更。
示例:
const deltaA = new Delta().insert('ABC');
const deltaB = new Delta().insert('D');
const transformed = deltaA.transform(deltaB, true);
console.log(transformed);
🛠️ 6.3 invert():生成撤销 Delta
Delta.invert()
会生成一个逆操作,用于实现撤销功能。
示例:
const original = new Delta().insert('Hello');
const change = new Delta().insert(' World');
const inverted = change.invert(original);
console.log(inverted);
// => [{ delete: 6 }]
🤖 7. AppFlowy 中 Delta 的应用
🔍 7.1 结合 Node Tree
- Node Tree 描述文档层次结构。
- Delta 专注于 TextNode 中的文本内容。
示例:
{
"type": "text",
"attributes": { "subtype": "heading", "heading": "h1" },
"delta": [
{ "insert": "🌟 Welcome to AppFlowy!" }
]
}
解释:
- Node Tree 决定该节点为
h1
标题。 - Delta 描述该标题内容。
🔍 7.2 事务管理(Transaction)
在 AppFlowy 中,每次编辑操作都会触发一个 Transaction
,其内部包含 Delta
。
示例:按下 Enter 键
{
"operations": [
{ "op": "insert", "path": [1], "nodes": [{ "type": "text", "delta": [{ "insert": "\n" }] }] },
{ "op": "update_text", "path": [0], "delta": [{ "retain": 5 }, { "insert": "\n" }] }
]
}
- 插入新行节点。
- 更新前一节点的文本内容。
🚀 8. Delta 的未来
随着协作编辑和富文本编辑需求的增长,Delta
格式仍具备强大的生命力和扩展性。 未来可能的改进方向:
- 🌐 支持更复杂的嵌套结构:结合 JSON Schema。
- ⚙️ 性能优化:更智能的合并与清理机制。
- 🤝 增强协作能力:融合 CRDT、OT 和区块链技术。
🎯 9. 结论
Delta
是一种基于操作的变更描述格式,核心围绕insert
、delete
、retain
三种操作展开。- 它更像是 文档的变更历史记录,而非最终内容的直接表达。
- AppFlowy 巧妙地融合了
Delta
和Node Tree
,实现了灵活的富文本编辑功能。
🌟 Delta 格式的本质: 以最小的操作描述文档内容及其变更历史,为富文本编辑和协作提供高效、灵活和易扩展的基础。 🚀