编辑器输入法问题解题思路

编辑器是一个复杂的工程,整个做下来会遇到很多问题,刚好自己最近也在做一款编辑器产品,中间遇到了一些问题,有一些新的解题思路,在这里总结和分享。

我做的这款产品是现代编辑器,由我的同事设计,因为此前他已经做过分享,在此只做简单的介绍;如果不了解我说的现代编辑器,不妨看看他的文章,我把链接放到了文章的末尾。

现代编辑器的设计

一般的现代编辑器为 3 层设计,在最上一层是用户看到的光标、文字选择区域等;第二层是文字、图片、样式的渲染;第三层是支持用户输入、剪贴板、数据存储、版本管理等,我这里称为数据层。有了以上的功能,用户就可以完成一些最基本的操作:内容选择、文字输入、复制粘贴、撤销重做等。我简单画了一张图:

编辑器设计图

本文针对数据层的输入法问题展开,因为我们需要在 IE 场景下使用,所以遇到的问题会相对多一些。

输入行为设计

在现代编辑中,输入行为不会直接落在渲染层上,一般情况会被一个隐藏区域的 textarea 元素捕获,这个元素在完成捕获后将内容同步到渲染层,如果用户输入的是中文,就需要结合输入法来完成整个输入工作,流程如下:

  1. compositionstart: 输入开始
  2. compositionupdate: 连续输入但未完成
  3. compositionend: 输入完成

textarea 元素触发 compositionend 事件后,被认为本次输入已完成,内容会在此时同步到渲染层上。

问题

在 IE 浏览器上,会因为搭配不同的输入法发生流程混乱现象,导致内容输入不正确,例如 IE 配合微软拼音输入法就容易在完成时多输入几个文字;常规做法是同时监听 keydownkeyup 事件,将整个输入过程记录并还原,最后将正确的内容同步到渲染层。

新的思路

将整行文字拆解成数据单元,再把光标前的字符预设到 textarea 上,输入完成后将 textarea 里面的内容与光标后面的内容拼接,完成输入。

举个例子,我们在编辑下面的一段 Hello world,此时我们的光标定位在 worldw 后面;源文如下:

1
<p style="font-size: 14px">Hello <strong>World</strong></p>

数据设计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"data": {
"tag": "p",
"style": [ { "font-size": "14px" } ],
"content": [
"Hello",
{
"tag": "strong",
"content": [ "World" ]
}
]
},
"selection": { "start": 7, "end": 7 }
}

此时 textarea 里的内容应该是 Hello W,当用户进行常规输入时,通过监听 input 事件即可重新组装数据并更新光标位置。

这个思路可以规避上述的问题,并且管理更少的事件监听,但是需要维护一套新的数据结构,如果做一款新的编辑器,不妨试一下这个方法。

参考

富文本编辑器的技术演进之路

如果文章对你有帮助,可通过支付宝赞赏本文

请发送邮件与我讨论:ARON.HQB@GMAIL.COM

未经授权,请勿转载