用户评论功能设计[二](实现回复功能)

在前面,咱们已是实现了用户评论功能以及评论的实时显示,如今,咱们来实现一下,用户的回复功能。实现效果以下所示:
javascript

回复评论的流程

咱们梳理一下评论回复流程:html

  1. 用户点击评论,input框获取焦点,input框的placeholder变为回复 @nickname
  2. 用户输入评论内容,而后提交,向服务器发出请求
  3. 在页面渲染用户评论内容

细心的同窗可能会发现,当回复成功后,顶部的xx条评论并无进行更新,由于在页面显示时,我并无将回复看成是评论来处理,因此数量并无增长java

回复功能逻辑实现

评论对象事件绑定

<li class="comment_li" v-for="(item,index) in commentList" :key="item.id" @click="replyUser(item,index,-1)" >...</li>
复制代码

从上面的代码,能够看出,咱们为每一个评论对象绑定了一个replyUser(item,index,-1)的事件。那咱们如今来看一下,咱们在replyUser函数中作了什么事情数据库

replyUser(item, index, index2) { 
      item.index = index; // 为每一个评论对象绑定一个index属性,这个index的做用是为了帮助咱们能更好的在commmentList中定位到该评论对象
      item.index2 = index2; // index2的做用是为了帮助咱们区分回复的级别。-1表明回复的是根评论,其余值表示回复的是别人的回复。
      this.replyUserComment = item;//replyUserComment的做用是为了保存当前的评论对象,在data中定义
      this.commentPlaceholder = `回复 @${item.nickname}:`;//修改placeHolder
      this.$refs.content.focus(); //input框获取焦点
    },
复制代码

通过上面的处理,咱们已经取得了咱们回复的评论对象。数组

对评论内容的处理

<div class="comment_input_box" v-show="commentPop">
    <input :placeholder="commentPlaceholder" class="comment_input" v-model="comment_text" ref="content" @click="checkComment" />
    <div class="comment_input_right" @click="checkComment">
      <i class="iconfont icon-fasong comment_i" :class="canSend?'comment_i_active':''">&#xe608;</i>
    </div>
</div>
复制代码

在这里,为input框绑定了一个checkComment事件,在实现简单评论功能时,它的逻辑是下面这样的:服务器

checkComment() {
      if (this.comment_text == "") {
        Toast("评论内容不能为空");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let to_user_id = ''; //由于评论是根评论,因此to_user_id和father_comment_id都为空
        let father_comment_id = '';
        const comment = this.comment_text;
        const video_id = this.video_id;
        const id = Date.now();
        const newComment = {
          avatar: this.userInfo.avatar,
          comment,
          id,
          create_time: "刚刚",
          nickname: this.userInfo.nickname
        };
        sendComment({ to_user_id, father_comment_id, comment, video_id }).then(
          val => {
            this.comment_text = "";
            this.hasSend = true;
            this.commentList.unshift(newComment);
          }
        );
      }
    },
复制代码
  1. 由于咱们一开始实现的评论功能是发布的根评论,没有要回复谁,因此to_user_idfather_comment_id咱们置空。
  2. 如今,咱们要进行的操做是回复用户评论。咱们须要明确回复的是哪一个用户,所回复的是哪条评论。由刚才的点击操做,咱们已经能够明确这两个信息了。所以,咱们要修改一下上面的逻辑:
checkComment() {
      if (this.comment_text == "") {
        Toast("评论内容不能为空");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let to_user_id = ''; //由于评论是根评论,因此to_user_id和father_comment_id都为空
        let father_comment_id = '';
        const comment = this.comment_text;
        const video_id = this.video_id;
        const id = Date.now();
        const newComment = {
          avatar: this.userInfo.avatar,
          comment,
          id,
          create_time: "刚刚",
          nickname: this.userInfo.nickname
        };
----------------------------------------------------
----------------------------------------------------
        if(this.replyUserComment){//若是评论对象不为null
            to_user_id = this.replyUserComment.from_user_id; // 让回复对象指向评论者
            father_comment_id = this.replyUserComment.id //让新评论的father_comment_id指向评论的id
        }
-------------------------------------------------------
-------------------------------------------------------
        sendComment({ to_user_id, father_comment_id, comment, video_id }).then(
          val => {
            this.comment_text = "";
            this.hasSend = true;
            this.commentList.unshift(newComment);
          }
        );
      }
    },
复制代码

实时渲染回复内容

如今已经实现了回复保存到数据库的功能。可是一样没有实时渲染到页面上。 所以,咱们要向以前同样,生成一个新的评论对象,并将这个对象插入到数组中去。但回复对象的插入与根评论的插入逻辑上存在差别,咱们先来看下面bilibili的评论图: ide

回复也能够看成评论进行回复。在项目中,咱们将回复划分为两类,一类是一级回复,一类是二级回复。函数


对于评论和回复来讲,通常采用的都是以下的嵌套的数据格式:ui

{
    avatar:'xxxxxxxxxxxx',
    nickname:'xxxxxxxxxxxxx',
    comment:'xxxxxxxxxxxxxx',
    crete_time:'xxxxxxxxxxxxx',
    child_comments:[
        {
             avatar:'xxxxxxxxxxxx',
            nickname:'xxxxxxxxxxxxx',
            comment:'xxxxxxxxxxxxxx',
            crete_time:'xxxxxxxxxxxxx',
        }
        ......
    ]
}
复制代码

  • 对于一级回复,咱们是直接插入到头部。
  • 对于二级回复,咱们是直接插入到尾部。 在前面replyUserComment回调函数中,咱们进行了以下处理:
replyUser(item, index, index2) { 
      item.index = index; // 为每一个评论对象绑定一个index属性,这个index的做用是为了帮助咱们能更好的在commmentList中定位到该评论对象
      item.index2 = index2; // index2的做用是为了帮助咱们区分回复的级别。-1表明回复的是根评论,其余值表示回复的是别人的回复。
      this.replyUserComment = item;//replyUserComment的做用是为了保存当前的评论对象,在data中定义
      this.commentPlaceholder = `回复 @${item.nickname}:`;//修改placeHolder
      this.$refs.content.focus(); //input框获取焦点
    },
复制代码

有了上面的图,咱们就能很好理解了。因而咱们对于一级回复,很容写出下面的代码:this

let index = this.replyUserComment.index;
let index2 = this.replyUserComment.index2;
if (this.replyUserComment.index2 == -1) {
//将一级回复插入到子评论的头部
this.commentList[index].child_comments.unshift(newComment);
} else {
//将二级回复插入到子评论的尾部
this.commentList[index].child_comments.push(newComment)
}
复制代码

完整代码

replyUser(item, index, index2) {
      item.index = index;
      item.index2 = index2;
      this.replyUserComment = item;
      this.commentPlaceholder = `回复 @${item.nickname}:`;
      this.$refs.content.focus();
    },
 checkComment() {
      if (this.comment_text == "") {
        Toast("评论内容不能为空");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let father_comment_id = ""; // 默认父评论为null
        let to_user_id = "";
        let video_id = this.video_id;
        let comment = this.comment_text;
        const id = Date.now();
        const newComment = {
          avatar: this.userInfo.avatar,
          comment,
          id,
          create_time: "刚刚",
          nickname: this.userInfo.nickname
        };
        if (this.replyUserComment) {
          // 说明不是根评论,而是子评论
          father_comment_id = this.replyUserComment.id; // 让father_comment_id 指向这个评论
          to_user_id = this.replyUserComment.from_user_id; // 让to_user_id指向父级评论的from_user_id
        }
        sendComment({ to_user_id, father_comment_id, comment, video_id }).then(
          val => {
            this.comment_text = "";
            this.hasSend = true;
            if (!this.replyUserComment) {
              this.commentList.unshift(newComment);
            } else {
              let index = this.replyUserComment.index;
              let index2 = this.replyUserComment.index2;
              if (this.replyUserComment.index2 == -1) {
                //回复一级人
                this.commentList[index].child_comments.unshift(newComment);
              } else {
                //回复二级人
                this.commentList[index].child_comments.push(newComment)
              }
            }
          }
        );
      }
    },
复制代码

到目前为止,用户的回复功能也是实现了,接下来,就相对轻松了,还剩下,评论功能的点赞。

未完待续....

相关文章
相关标签/搜索