• contenteditable H5聊天室发送表情


    遇到个需求是在H5页面聊天室中可以发送表情,普通的发送信息已经做过了是借助的websocket,发表情类似于QQ微信那样,既需要展示在输入框中,又需要发送给后台,回显到聊天室让大家都看到,这个还是需要仔细考虑考虑的。

    涉及到的功能点有以下几个:

    1.仿照qq微信,输入框中要回显文字和表情,支持删除和插入。

    2.输入框右侧有个表情按钮,点击按钮底部弹出表情区域,点击可以插入到“输入框”的光标位置。

    3.输入框的高度有一定限制,超出后滚动。

    对应的解决方案:

    1.这里用普通的input或其他是显示不了表情的,需要借助div的contenteditable属性,经查证qq空间的动态也是用的这个,表情有两种方案:1.选用emoji表情,优点是全世界通用,无需解析使用简单,适配性强,缺点是个性化不高,观赏度不强。2.自己制定系统内的表情规则,比如动态解析展示,所谓的表情其实是图片,优点是可以DIY表情,可以根据自己项目风格设计,缺点是每次展示都需要解析,而且要处理删除逻辑等。在此选用方案1。

    2.功能简单

    3.功能简单

    (2023.09.27补充)本文后续有更新,考虑到顺便记录解题过程,之前文章内容就暂不更改了,新增内容以追加方式由分割线显示,想要最终结果的直接翻到页面底部即可

    技术栈vue2,核心代码参考如下:

    1. // @/components/input.vue
    2. <template>
    3. <div ref="editor" class="custom-input" contenteditable="true" @input="inputText" @blur="inputBlur" @focus="inputFocus">div>
    4. template>
    5. <script>
    6. export default {
    7. props: ['value'],
    8. data() {
    9. return {
    10. isBlur: true, // 解决赋值时光标自动定位到起始位置
    11. }
    12. },
    13. watch: {
    14. value(val) {
    15. console.log(val);
    16. if (this.isBlur) {
    17. this.$refs.editor.innerHTML = val;
    18. }
    19. }
    20. },
    21. mounted() {
    22. document.execCommand("defaultParagraphSeparator", false, "")
    23. },
    24. methods: {
    25. // 获取标签内容
    26. getInnerHTML() {
    27. return this.$refs.editor.innerHTML
    28. },
    29. // 监听输入框内容
    30. inputText() {
    31. this.$emit('input', this.$refs.editor.innerHTML);
    32. },
    33. inputFocus() {
    34. this.isBlur = false;
    35. },
    36. inputBlur() {
    37. this.isBlur = true;
    38. this.$emit('input', this.$refs.editor.innerHTML);
    39. }
    40. }
    41. }
    42. script>
    43. <style lang="less" scoped>
    44. .custom-input{
    45. width: 100%;
    46. max-height: 1.48rem;
    47. overflow-y: auto;
    48. line-height: 0.48rem;
    49. outline: #D3D3D3 auto 1px;
    50. padding-left: 1px;
    51. &:focus-visible {
    52. // outline: -webkit-focus-ring-color auto 1px;
    53. outline: #D3D3D3 auto 1px;
    54. }
    55. &:empty::before {
    56. content: attr(placeholder);
    57. font-size: 14px;
    58. color: #CCC;
    59. line-height: 21px;
    60. padding-top: 20px;
    61. }
    62. }
    63. style>
    1. // index.vue