写在前面
在线文档的产品想必大家都应该用过,诸如 google、wps、石墨、腾讯和飞书等等。
对于前端同学来说,在线文档可以算是前端技术天花板之一了。在我初入前端的时候,我就觉得这个东西可望而不可即。时常想加入那样的团队,但又怕自己水平有限。近几年有幸参与过文档的一些开发工作,所以想借此机会写点东西留个痕。虽然现在 AI 来了,但我还是得坚持手搓✍🏻。
我是第一次接触文档才知道 block 架构这种东西的,所以如果你是第一次听到 block 架构也很正常,毕竟一般情况下咱也用不上😄,不过多知道一点能让你更好的装下13。
最简版
通常来说一篇文档可以由大标题、文本、列表、表格、图片、代码块、iframe、图表等各种元素组成,只要你兼容做得好,想要往文档里嵌入任何东西都是有可能的。
假如我们要做一个文档编辑器,最容易想到的数据结构大概长下面这个这样子:
json
{
"type": "page",
"children": [
{ "type": "text", "text": "第一段内容" },
{ "type": "image", "url": "https://example.com/xxx.png" },
{ "type": "text", "text": "第二段内容" },
{ "type": "chart", "data": "{}" },
]
}
然后前端渲染的时候只要递归遍历 children,根据 type 找到对应组件就行了,看起来很合理。小文档这样写确实一点毛病没有,简单点的表单搭建也是类似的思路。
但是文档一大,真正的麻烦就来了:
- 一篇文档有几万个段落,难道一次性全部塞进 dom?
- 每输入一个字,都重新渲染整篇文档?
- 两个人同时编辑同一片区域,undo 到底撤销谁的操作?
- 图片加载后高度变了,为什么页面不会突然跳走?
- 同一段内容出现在多个页面里,怎么做到改一处、处处更新?
- 文档还没下载完,为什么首屏已经能看,甚至已经能编辑了?
- 修改深层节点,需要在一棵大树里定位。
- 移动节点时,要同时维护多个嵌套对象。
- 多人协同时,很难精确描述"谁改了哪一块"。
- 分页加载时,半棵树到了、半棵树没到,不好表达。
- 同一份内容出现在多个位置时,只能复制数据。
- 文档数据过大,又该如何进行压缩?
这些问题背后,藏着数据存储、运行时树、富文本输入、协同编辑、虚拟布局、插件扩展等一整套系统。所以成熟的文档编辑器通常不会把整篇文档只当成一棵巨大的嵌套 json。
于是乎 block 架构就出现了。
结语
哈哈哈,这篇文章只是抛个砖,上面提到的问题会在下一篇文章中一一说明。大家有兴趣的话可以点个赞哈哈哈哈哈。在写了,在写了,给我一点时间😂。。。。。。