荐 Vue+element如何让帖子评论带上emoji,这个需求让我在富文本Quill开始了踩坑连连看

2022-08-08,,,,

天降巨坑1:Quill富文本输入的内容提交后显示的有文本+标签

到底是个啥说不明道不白的情况,来看看效果图:

emm…看起来让人感觉真是怪别扭的。

我也是前前后后想了很多种办法,却忽略了一种最原始的!最简单的!直接将输入的内容中的<>标签符号替换成空字符串不就完事了吗。

二话不说定位一下这个发表评论的核心代码位置。

先来来看看这个button:

<div class="reply-btn-box" style="text-align:center">
      <el-button
        class="reply-btn"
        size="medium"
        @click="sendQuillComment"
        type="primary"
        >发表</el-button
      >
    </div>

绑定的sendQuillComment点击事件:

    sendQuillComment() {
      if (!this.$refs.postForm.form.content) {
        this.$message({
          showClose: true,
          type: 'warning',
          message: 'quill评论不能为空'
        })
      } else {
        let a = {}
        let input = document.getElementById('quillInput')
        let timeNow = new Date().getTime()
        let time = this.dateStr(timeNow)
        a.name = this.myName
        a.comment = this.$refs.postForm.form.content.replace(/<[^>]+>/g, '')
        a.headImg = this.myHeader
        a.time = time
        a.commentNum = 0
        a.like = 0
        this.comments.push(a)
        this.replyComment = ''
        input.innerHTML = ''
      }
    },

聪明的同学一眼就看到了重点:

a.comment = this.$refs.postForm.form.content.replace(/<[^>]+>/g, '')

我们再简化一下,到底是哪一步在去除<>标签:

replace(/<[^>]+>/g, '')

这不是整挺好了吗

天降巨坑2:Vue+element+Emoji+Quill

最最最最核心就是为了实现评论时能选择emoji的功能。

评论,包括二级评论都是不啥难事哈,带emoji是不是有点调皮了。

等全部完事了,我会总结一篇《如何通过Vue+element实现帖子评论功能》给大家作为参考,类似于贴吧论坛盖楼。

那么回归正题哈,一开始我的想法是把emoji这个功能单独抽出来做个组件。下面先说一下实现的过程。

方法一

第一步,引入JSON文件:

const appData = require("../static/utils/emoji.json");

JSON文件具体内容如下:

<style lang="scss">
/* el-popover是和app同级的,所以scoped的局部属性设置了无效 */
/* 需要设置全局style */
  .el-popover{
    height:200px;
    width:400px;
    overflow: scroll;
    overflow-x:auto;
  }
</style>

<style scoped>
.chatIcon {
  padding: 0 10px;
  font-size: 25px;
}
.emotionList{
  display: flex;
  flex-wrap: wrap;
  padding:5px;
}
.emotionItem{
  width:10%;
  font-size:20px;
  text-align:center;
}
/*包含以下四种的链接*/
.emotionItem {
    text-decoration: none;
}
/*正常的未被访问过的链接*/
.emotionItem:link {
    text-decoration: none;
}
/*已经访问过的链接*/
.emotionItem:visited {
    text-decoration: none;
}
/*鼠标划过(停留)的链接*/
.emotionItem:hover {
    text-decoration: none;
}
/* 正在点击的链接*/
.emotionItem:active {
    text-decoration: none;
}
</style>

第二步:template

表情框组件,通过slot插槽按钮触发显示;输入框是一个textarea,我们要把点击选择的表情插入到textarea光标对应的位置之后:

<div class="chatIcon">
    <el-popover placement="top-start" width="400" trigger="click" class="emoBox">
        <div class="emotionList">
            <a href="javascript:void(0);" @click="getEmo(index)" v-for="(item,index) in faceList" :key="index" class="emotionItem">{{item}}</a>
        </div>
        <el-button
        class="emotionSelect"
        icon="iconfont icon-biaoqing"
        slot="reference"
        ></el-button>
    </el-popover>
</div>
<el-input
  v-model="textarea"
  class="chatText"
  resize="none"
  type="textarea"
  id='textarea'
  rows="5"
  @keyup.enter.native="sendInfo"
></el-input>

第三步:css

由于el-popover比较特殊,需要全局设置el-popover样式,并防止污染全局:

<style lang="scss">
/* el-popover是和app同级的,所以scoped的局部属性设置了无效 */
/* 需要设置全局style */
  .el-popover{
    height:200px;
    width:400px;
    overflow: scroll;
    overflow-x:auto;
  }
</style>

<style scoped>
.chatIcon {
  padding: 0 10px;
  font-size: 25px;
}
.emotionList{
  display: flex;
  flex-wrap: wrap;
  padding:5px;
}
.emotionItem{
  width:10%;
  font-size:20px;
  text-align:center;
}
/*包含以下四种的链接*/
.emotionItem {
    text-decoration: none;
}
/*正常的未被访问过的链接*/
.emotionItem:link {
    text-decoration: none;
}
/*已经访问过的链接*/
.emotionItem:visited {
    text-decoration: none;
}
/*鼠标划过(停留)的链接*/
.emotionItem:hover {
    text-decoration: none;
}
/* 正在点击的链接*/
.emotionItem:active {
    text-decoration: none;
}
</style>

第四步:script

mounted() {
    for(let i in appData){
      this.faceList.push(appData[i].char);
    }
},
data() {
    return {
      faceList: [],
      textarea: ""
    };
},
method(){
    getEmo(index){
        var textArea=document.getElementById('textarea');
        function changeSelectedText(obj, str) {
          if (window.getSelection) {
            // 非IE浏览器
            textArea.setRangeText(str);
            // 在未选中文本的情况下,重新设置光标位置
            textArea.selectionStart += str.length;
            textArea.focus()
          } else if (document.selection) {
            // IE浏览器
            obj.focus();
            var sel = document.selection.createRange();
            sel.text = str;
          }
        }
        changeSelectedText(textArea,this.faceList[index]);
        this.textarea=textArea.value;// 要同步data中的数据
        // console.log(this.faceList[index]);
        return;
      },
}

写完方法一,随之而来的一个问题是:我想用什么表情得先添加到JSON文件里,这样非常不方便,于是才有了方法二的出现。

方法二:使用quill-emoji

第一步:引入并注册

import dedent from 'dedent'
import { Quill, quillEditor } from 'vue-quill-editor'
import quillEmoji from 'quill-emoji'
import 'quill-emoji/dist/quill-emoji.css'

Quill.register('modules/quillEmoji', quillEmoji)

别忘了install这几个库

第二步:

export default {
  components: {
    Drawer,
    quillEditor
  },
  data() {
    return {
      content: dedent`
          <p><span data-name="grinning"><span contenteditable="false"><span class="ap ap-grinning"></span></span></span></p>
        `,
      editorOption: {
        theme: 'snow',
        modules: {
          'emoji-toolbar': true,
          'emoji-shortname': true,
          toolbar: {
            container: ['emoji']
          }
        }
      }
    }
   }
 }

第三步:应用

 <quill-editor
      class="editor"
      v-model="content"
      :options="editorOption"
    />

Quill里的emoji有多丰富呢?

要啥啥都有,Quill真香!

推荐大家使用方法二,这样可以避免巨坑一,发表评论时不会再有任何<>标签符乱入了。

本文地址:https://blog.csdn.net/weixin_42224055/article/details/107249967

《荐 Vue+element如何让帖子评论带上emoji,这个需求让我在富文本Quill开始了踩坑连连看.doc》

下载本文的Word格式文档,以方便收藏与打印。