如何不借助 contentEditable 实现富文本编辑器?

如何不借助 contentEditable 实现富文本编辑器?

问题

现在主流的web富文本编辑器几乎都是基于contentEditable的,我们之前的编辑器引擎就是基于TinyMCE魔改的,这个引擎目前只有我一个人负责。富文本编辑器是我们的核心业务,现在leader要搞一个专门的富文本编辑器团队,开发类似于Google docs那种不基于contentEditable的编辑器引擎,这完全是另一个级别的事情了,我找遍了全网也找不到类似还活着的开源项目。除了代码编辑器ace之外真的一无所获,有没有做过的大佬稍微讲一下思路,要实现那些关键组件?或者讲一下大家团队一开始是怎么入手的?

链接:https://www.zhihu.com/question/366666295/answer/976815981

解决

能提出这个问题,说明题主有过很仔细的思考。我尝试借此澄清一个大家入门 Web 富文本编辑时可能的误解吧:

在浏览器里,打开了 contentEditable 不等于**借助了** contentEditable。这是什么意思呢?

  • 打开了 contentEditable,意味着页面这个区域内**具备了进行富文本编辑的能力**。
  • 借助了 contentEditable,意味着**依赖了浏览器默认的富文本编辑行为**。

粗略看来,一个 DOM 元素加上 contentEditable 属性后,就大致具备了这些能力:

  • 选区的拖选编辑和光标闪动支持
  • 方向键控制时的默认行为
  • 输入文字时的默认行为(牵扯到输入法)
  • 复制粘贴时的默认行为(牵扯到富文本剪贴)

主流浏览器都会给你一套开箱即用的方案,让你用一行代码即可实现富文本编辑器。但天下没有免费的午餐,像这种最简单的方案就有传说中的不兼容的问题。比如同样一个加粗操作,没人规定浏览器是应该给文本套个 <b> 标签还是给 <span> 加个 font-weight:bold; 的 CSS 样式来实现(印象里 Chrome 是直接套 span 的,说好的语义化呢)。于是最后在 Chrome 和 Firefox 里互相编辑的产物,就必然是不可控、不可预期的了。很多人说富文本做起来很脏,这就是原因之一。

所以还是那句老话,完全依赖别人现成的技术是会被卡脖子的。相应地,Facebook 的 DraftJS 虽然不太好用,但代表了一种 React 思潮引领下的富文本新思路(大概率不是它首创,但这么说起来方便前端同学们理解),简单来说是这样的:

  1. 同样用 contentEditable,但只关心它的选区 (Selection) 状态。
  2. 输入文本时,以 nextState = f(selection, input) 理念计算出新状态。

这样看来,整个编辑器就像是一个 React 中的受控组件了。关键的受控行为大概包括这些:

  • 按键输入被拦截,基于 f(selection, input) 计算出新状态
  • 复制粘贴被拦截,基于 f(selection, input) 计算出新状态
  • DOM 更改被拦截,基于 nextState 单向地渲染出 DOM 状态

那么,还有哪些地方需要依赖 contentEditable 呢?其实就是和 Selection 强相关的东西:

  • **选区高亮状态**依赖 contentEditable,否则你需要自己渲染那个「拖蓝」区域。
  • **点击后的选中状态**依赖 contentEditable,否则你需要自己计算某个坐标下对应了哪个文字,意味着要自己去解析字体参数做文本排版,这是天坑。
  • **方向键操作后的状态**依赖 contentEditable,理由同上。

我相信看到这里,有经验的前端同学已经知道怎样开始尝试「不借助 contentEditable 的默认行为来实现富文本编辑器」了吧。当然,我已经挺久没做富文本了,上面一些概念可能与具体细节有些出入,欢迎大家指正。

注意,许多实际工程做起来,绝不是知道个原理就够了。富文本在细节层面有非常多麻烦的地方,除非实力雄厚如 Google,否则不推荐大家在商业项目里完全从头做起。具体可参考我的这个回答: 有多大比例的前端工程师,能在合理时间内独立开发出一个足以商用的富文本编辑器?

具体到实际项目,ProseMirror 和 Slate 的框架化设计都很不错。我相信它们是开发「自主可控」的富文本编辑器时的正解。许多历史经验已经告诉我们,自主可控未必意味着完全自己从头写,而是要掌控对满足自己未来需求的控制权。在这小小的富文本编辑器里,不也是这样吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值