之前一直很好奇富文本编辑器中的各种元素是怎么插入的,最近刚好项目中有关功能需要用到富文本的一丁点功能,所以才得以了解可实现富文本编辑器的一个途径。
元素的contenteditable
属性正是可以替代textarea
,实现复杂文本输入的一种解决方案。当给元素加上contenteditable="true"
时,这个元素就类似于input type="textarea"
可输入。输入的内容会作为文本节点插入到父节点中:
但是与textarea
、input
等输入框不同的是,textarea
、input
失去焦点后想插入修改值,就必须改变该节点的value
值,并且只能插入文本;而contenteditable=true
的元素则需要直接操作DOM,并且可以插入任何HTML元素,从而实现富文本编辑的功能。
可编辑元素与业务之间的联系与区别
联系
由于需求中提出需要一键插入与文本颜色不同的#微信昵称#
占位符,而普通的文本输入显然是不能满足的,所以可编辑元素是最好的选择。
区别
我们的输入内容最终是要通过企业微信发送给客户的,所以不能包含HTML标签,而可编辑元素在处理用户回车等操作时,是会在内容中插入HTML标签的;我们的需求也不需要在内容中加入加粗、斜体、等特殊格式,除了昵称,我们不需要用标签来包裹任何文本,并且最后昵称也是要过滤掉标签。
Selection对象
根据MDN
上的描述,Selection
对象目前还是一个实验性的功能,使用window.getSelection()
可以获取到Selection
对象,在我们要实现的功能中,需要通过这个对象获取标签的位置信息,从而达到插入表情和微信昵称dom
节点的目的。
遇到的坑
光标所在位置与节点类型之间的关系
除了直接输入,富文本还有一种功能就是直接在内容中插入节点,这个节点可以分为文本节点和dom
节点;文本节点就是普通的字符,包括表情,dom
节点则是像我们项目中需要插入蓝色的#微信昵称#
占位符。在我们计算光标所在位置时,Selection
对象对于两种不同的节点返回的位置属性anchorOffset
和focusOffset
是不一样的;
各浏览器对不同输入处理的差异
回车
- Chrome:
- Firefox:
- IE:
空格
- Chrome:
- Firefox:
- IE:
复制粘贴
普通的输入框粘贴时会自动过滤掉节点标签,但是粘贴到contenteditable
为true
的可编辑区域却不会过滤掉文本节点的标签,所以需要将粘贴内容做进一步的过滤。
并且复制的内容中可能会包含换行和空格的情况,所以要进一步考虑上面提到的问题。