## 1 引言

[「可视化搭建系统」——从设计到架构，探索前端的领域和意义](https://juejin.im/post/6854573220532748302) 这篇文章主要分析了现阶段可视化搭建的几种表现形式和实现原理，并重点介绍了基于富文本的可视化搭建思路，让人耳目一新。

基于富文本的可视化搭建看似很新颖，但其实早就被广泛使用了，任何一个富文本编辑器几乎都有插入表格功能，这就是一个典型插入自定义组件的场景。

使用过 [语雀](https://www.yuque.com/) 的同学应该知道，这个产品的富文本编辑器可以插入各种各样自定义区块，是 “最像搭建” 的富文本编辑器。

那么积木式搭建和富文本搭建存在哪些差异，除了富文本更倾向于记录静态内容外，还有哪些差异，两者是否可以结合？本文将围绕这两点进行讨论。

## 2 精读

还是先顺着原文谈谈对可视化搭建的理解：

可视化搭建是通过可视化方式代替开发。**前端代码开发主要围绕的是 html + js + css**，那么无论是 markdown 语法，还是创建另一套模版语言亦或 JSON 构成的 DSL，**都是用一种 dsl + 组件 + css 的方式代替 html + js + css**，可视化搭建则更进一步，用 ui 代替了 dsl + 组件，**即精简为 ui 操作 + css**。

可以看到，这种转换的推演过程存在一定瑕疵，因为每次转换都有部分损耗：

**用 dsl + 组件 代替 html + js。**

如果 dsl 拓展得足够好，理论上可以达到 html 的水平，尤其在垂直业务场景是不需要那么多特殊 html 标签的。

但用组件代替 js 就有点奇怪了，首先并不是所有 js 逻辑都沉淀在组件里，一定有组件间的联动逻辑是无法通过一个组件 js 完成的，另一方面如果将 js 逻辑寄托在组件代码里，本质上是没有提效的，用源码开发项目与开发搭建平台的组件都是 pro code，更极端一点来说，无论是组件间联动还是整个应用都可以用一个组件来写，那搭建平台就无事可做了，这个组件也成了整个应用，game over。

为了弥补这块缺憾，低代码能力的呼声越来越高，而低代码能力的核心在于设计是否合理，比如暴露哪些 API 可以覆盖大部分需求？写多少代码合适，如何以最小 API 透出最大弥补组件间缺失的 js 能力？目前来看，以状态数据驱动的低代码是相对优雅的。

**用 ui 操作 代替 dsl + 组件。**

UI 操作并不是标准的，相比直接操作模版或者 JSON DSL，UI 化后就仁者见仁智者见智了，但 UI 化带来的效率提升是巨大的，因为所见即所得是生产力的源泉，从直观的 UI 布局来看，就比维护代码更轻松。但 UI 化也存在两个问题，一个是可能有人觉得不如 markdown 效率高，另一个是功能有丢失。

对于第一点 UI 操作效率不如 markdown 高，可能很多程序员都崇尚用 markdown 维护文档而不是富文本，原因是觉得程序员维护代码的效率反而比所见即所得高，但那可能是错觉，原因是还没有遇到好用的富文本编辑器，体验过语雀富文本编辑器后，相信大部分程序员都不会再想回头写 markdown。当然语雀富文本战胜 markdown 的原因有很多，我觉得主要两点是吸收并兼容了 markdown 操作习惯，与支持了更多仅 UI 能做到的拓展能力，对 markdown 形成降维打击。

第二点功能丢失很好理解，markdown 有一套标准语法和解析器可以验证，但 UI 操作并没有标准化，也没有独立验证系统，如果无法回退到源码模式，UI 没有实现的功能就做不到。

回到富文本搭建上，其实富文本搭建和普通网页构建并没有本质区别。html 是超文本标记语言，富文本是跨平台文档格式，从逻辑上这两个格式是可以互转的，只要富文本规则作出足够多的拓展，就可以大致覆盖 html 的能力。

但富文本搭建有着显著的特征，就是光标。

### 积木式搭建和富文本搭建的区别

富文本以文本为中心，因此编辑文字的光标会常驻，编辑的核心逻辑是排版文字，并考虑如何在文字周围添加一些自定义区块。

有了光标后，圈选也非常重要，因为大家编辑文字时有一种很自然的想法是，任何文字圈选后复制，可以粘贴到任何地方，那么所有插入到富文本中的自定义组件也要支持被圈选，被复制。

实际上富文本内插入自定义区块也可以转换为积木式搭建方案解决，比如下面的场景：

```text
文本 A
图表 B
文本 C
```

我们在文本 A 与 文本 C 之间插入图表 B，也可以理解为拖拽了三个组件：文本组件 A + 图表组件 B + 文本组件 C，然后分别编辑这三个组件，微调样式后可以达到与富文本一样的编辑效果，甚至加上自由布局后，在布局能力上会超越富文本。

虽然功能层面上富文本略有输给积木式搭建，但富文本在编辑体验上是胜出的，对于文字较多的场景，我们还是会选择富文本方式编辑而不是积木式搭建拖拽 N 个文本组件。

所以微软 OneNote 也吸取了这个经验，毕竟笔记本主要还是记录文字，因此还是采用富文本的编辑模式，但创造性的加入了一个个独立区块，点击任何区域都会创造一个区块，整个文档可以由一个区块构成，也可以是多个区块组合而成，这样对于连贯性的文字场景可以采用一个富文本区块，对于自定义区块较多，比如大部分是图片和表格的，还可以回到积木式搭建的体验。由于 OneNote 采用绝对定位模拟流式布局的思路，当区块重叠时还可以自动挤压底部区块，因此多区块模式下编辑体验还是相对顺畅的。

可以看出来这是一种结合的尝试，从前端角度来看，富文本本质上是对一个 div 进行 contenteditable 申明，那么一个应用可以整体是 contenteditable 的，也可以局部几个区块是，这种代码层面的自由度体现在搭建上就是积木式搭建可以与富文本搭建自由结合。

### 积木式搭建与富文本搭建如何结合

对于积木式搭建来说，富文本只是其中一个组件，在不考虑有富文本组件时是完全没有富文本能力的。比如一个搭建平台只提供了几个图表和基础控件，你是不可能在其基础上使用富文本能力的，甚至连写静态文本都做不到。

所以富文本只是搭建中一个组件，就像 contenteditable 也只能依附于一个标签，整个网页还是由标签组成的。但对于一个提供了富文本组件的积木式搭建系统来说，文字与控件混排又是一个痛点，毕竟要以一个个区块组件的方式去拖拽文本节点，成本比富文本模式大得多。

所以理想情况是富文本与整个搭建系统使用同一套 DSL 描述结构，富文本只是在布局上有所简化，简化为简单的平铺模式即可，但因为 DSL 描述打通，富文本也可以描述使用搭建提供的任意组件嵌套在内，所以只要用户愿意，可以将富文本组件拉到最大，整个页面都基于富文本模式去搭建，这就变成了富文本搭建，也可以将富文本缩小，将普通控件以积木方式拖拽到画布中，走积木式搭建路线。

用代码方式描述积木式搭建：

```html
<bar-chart />
<div>
  <p>header</p>
  <line-chart />
  <p>footer</p>
</div>
```

上述模式需要拖拽 `bar-chart`、`div`、`p`、`line-chart`、`p` 共 5 个组件。富文本模式则类似下面的结构：

```html
<bar-chart />
<div contenteditable>
  <p>header</p>
  <line-chart />
  <p>footer</p>
</div>
```

只要拖拽 `bar-chart`、`div` 两个组件即可，`div` 内部的文字通过光标输入，`line-chart` 通过富文本某个按钮或者键盘快捷键添加。

可以看到虽然操作方式不同，但本质上描述协议并没有本质区别，我们理论上可以将任何容器标签切换为富文本模式。

## 3 总结

富文本是一种重要的交互模式，可以基于富文本模式做搭建，也可以在搭建系统中嵌入富文本组件，甚至还可以追求搭建与富文本的结合。

富文本组件既可以是搭建系统中一个组件，又可以在内部承载搭建系统的所有组件，做到这一步才算是真正发挥出富文本的潜力。

> 讨论地址是：[精读《可视化搭建思考 - 富文本搭建》· Issue #262 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/262)

**如果你想参与讨论，请 [点击这里](https://github.com/dt-fe/weekly)，每周都有新的主题，周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**

> 关注 **前端精读微信公众号**

<img width=200 src="https://img.alicdn.com/tfs/TB165W0MCzqK1RjSZFLXXcn2XXa-258-258.jpg">

> 版权声明：自由转载-非商用-非衍生-保持署名（[创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh)）
