上一篇文章,我们通过一个富文本组件并为其自定义了v-module,使其像表单元素一样支持双向数据绑定。但还有不小问题。比如输入回车换行,会在文本上包裹html标签。Chrome中是div,IE中是p,Firefox中是br。当然这些附加的标签在浏览器中显示是Ok的,但有的终端是不支持html标签的,因此得转换它们。
代码实现
最先想到的是用正则表达式来替换,但不太好匹配,写起来很复杂,改了几版还是有问题。后来换了个思路终于搞定。
insertReturn (el) {
const range = document.createRange()
//返回用户当前的选区
const sel = document.getSelection()
//获取当前光标位置
const offset = sel.focusOffset
//div当前内容
const content = el.innerHTML
//添加换行符
let separator = '\n'
// 光标在文本最后
if (offset === content.length) {
separator = '\n\r'
}
el.innerHTML = content.slice(0, offset) + separator + content.slice(offset)
//设置光标为当前位置
range.setStart(el.childNodes[0], offset + 1)
//使得选区(光标)开始与结束位置重叠
range.collapse(true)
//移除现有其他的选区
sel.removeAllRanges()
//加入光标的选区
sel.addRange(range)
},
handleKeyDown(event) {
event.preventDefault()
this.insertReturn(event.target)
}
这里我们为可编辑div新增了handleKeyDown处理函数,使用event.preventDefault()取消了浏览器在文本回车换行的默认行为。用insertReturn方法来统一处理:使用回车换行来分割字符串,如果是在文本中间用\r\n,文本开头用\n就可以了。代码都有注释,就不细讲了。
参考
- 访问codesandbox查看完整实例代码及最终效果。
关于range可以参考我之前写的开发在线文本编辑器。
Happy code!
评论 (0)