之前一直很好奇富文本编辑器中的各种元素是怎么插入的,最近刚好项目中有关功能需要用到富文本的一丁点功能,所以才得以了解可实现富文本编辑器的一个途径。

元素的contenteditable属性正是可以替代textarea,实现复杂文本输入的一种解决方案。当给元素加上contenteditable="true"时,这个元素就类似于input type="textarea"可输入。输入的内容会作为文本节点插入到父节点中:截屏2021-04-20 下午11.27.22

但是与textareainput等输入框不同的是,textareainput失去焦点后想插入修改值,就必须改变该节点的value值,并且只能插入文本;而contenteditable=true的元素则需要直接操作DOM,并且可以插入任何HTML元素,从而实现富文本编辑的功能。

可编辑元素与业务之间的联系与区别

联系

由于需求中提出需要一键插入与文本颜色不同的#微信昵称#占位符,而普通的文本输入显然是不能满足的,所以可编辑元素是最好的选择。

区别

我们的输入内容最终是要通过企业微信发送给客户的,所以不能包含HTML标签,而可编辑元素在处理用户回车等操作时,是会在内容中插入HTML标签的;我们的需求也不需要在内容中加入加粗斜体、等特殊格式,除了昵称,我们不需要用标签来包裹任何文本,并且最后昵称也是要过滤掉标签。

Selection对象

根据MDN上的描述,Selection对象目前还是一个实验性的功能,使用window.getSelection()可以获取到Selection对象,在我们要实现的功能中,需要通过这个对象获取标签的位置信息,从而达到插入表情和微信昵称dom节点的目的。

Snipaste_2021-05-27_17-04-18

遇到的坑

光标所在位置与节点类型之间的关系

除了直接输入,富文本还有一种功能就是直接在内容中插入节点,这个节点可以分为文本节点和dom节点;文本节点就是普通的字符,包括表情,dom节点则是像我们项目中需要插入蓝色的#微信昵称#占位符。在我们计算光标所在位置时,Selection对象对于两种不同的节点返回的位置属性anchorOffsetfocusOffset是不一样的;

各浏览器对不同输入处理的差异

回车
  1. Chrome:
  2. Firefox:
  3. IE:
空格
  1. Chrome:
  2. Firefox:
  3. IE:

复制粘贴

普通的输入框粘贴时会自动过滤掉节点标签,但是粘贴到contenteditabletrue的可编辑区域却不会过滤掉文本节点的标签,所以需要将粘贴内容做进一步的过滤。

并且复制的内容中可能会包含换行和空格的情况,所以要进一步考虑上面提到的问题。


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

到店业务逻辑梳理 上一篇
通过vue源码阅读解决的问题 下一篇