input文本中间插入表情光标位置错乱?

背景

最近打算在博客里添加一个聊天室功能,进入博客的人可以在聊天室中聊天,同时也引入了一个人工智能机器人。聊天室使用 websocket 实现,聊天室支持发送emoji表情,本来打算找一个库用一下,但是后面考虑到要添加一些自定义的表情,就自己写了一个。在用户可以发送文本和emoji表情,但是当用户在文本中间插入emoji时,问题就出现了!

问题

当用户在文本框中输入文字以后,把光标移到文本中间位置,点击添加emoji表情,结果emoji出现在了文本最后面。如下图:

image.png

预期结果是,在 ‘我的’ 后面添加 emoji表情。当点击emoji表情后,结果如下:

image.png

分析原因

一开始写的时候没有考虑到这个问题,逻辑是在用户点击添加emoji表情时,会把表情拼接在文本后面。那么如果我们想在 ‘我的’ 后面添加 emoji表情 该怎么处理呢?在文字的中间加入内容,第一想法就是获取光标所在位置的下标,把内容截断,把emoji拼接在中间。但是浏览器有没有办法去获取光标的位置呢?答案是有的。

解决方案

在搜集了资料以后,我把目光投向了

// 用于设定 input和textarea 元素中当前选中文本的起始和结束位置。
element.setSelectionRange(selectionStart, selectionEnd [, selectionDirection])
- selectionStart     选中的起始下标
- selectionEnd       选中的结束下标
- selectionDirection   选择方向
复制代码

我们尝试在点击表情的时候获取input中光标的selectionStart,然后从下标出截断,把表情拼进去,代码如下:

image.png

可以,效果已经实现了,但是还有个小问题。表情插入进去以后,你的光标聚焦会在文本的末尾(如下图),而不是在插入的emoji表情后面,我们如何把光标位置定位到表情后面呢?这就用到了setSelectionRange

image.png

二次解决

setSelectionRange用于设定 input和textarea 元素中当前选中文本的起始和结束位置,当selectionStartselectionEnd相等的时候(相当于选中某一个位置),就会在选中位置添加光标。 做法如下:

image.png

这样就完美解决了。关于为什么要加 setTimeout ,如果不加 setTimeout 在chrome中是不起作用的。查阅资料显示在chrome中会先执行 setSelectionRange 之后才会进行focus操作。所以添加 setTimeout 延迟执行。(撰文不易,点赞鼓励)

-更多内容前往 前端知识总结

猜你喜欢

转载自juejin.im/post/7047025292292030477