In the previous, we have implemented the user comment function and real-time display of comments, now, let’s implement the user reply function. The implementation effect is as follows:

Process for responding to comments

Let’s review the comment response process:

  1. The user clicks on the comment,inputBox gets focus,inputThe boxplaceholderintoReply @ nickname
  2. The user enters a comment and submits it, making a request to the server
  3. Render user comments on the page

Careful students may find that when the reply is successful, the top of theXx commentsI didn’t update it because I didn’t treat the responses as comments when the page was displayed, so the number didn’t increase

Return function logic implementation

Comment object event binding

 <li
  class="comment_li"
  v-for="(item,index) in commentList"
  :key="item.id"
  @click="replyUser(item,index,-1)"
>.</li>
Copy the code

From the code above, you can see that we bind a replyUser(item,index,-1) event to each comment object. So what are we doing in the replyUser function

replyUser(item, index, index2) { 
      item.index = index; // Bind an index attribute to each comment object. This index is used to help us better locate the comment object in the commmentList
      item.index2 = index2; // Index2 is used to help us distinguish the level of reply. -1 indicates that the reply is a root comment, and other values indicate that the reply is from someone else.
      this.replyUserComment = item;//replyUserComment is used to save the current comment object, defined in data
      this.commentPlaceholder = ` reply @${item.nickname}: `;/ / modify the placeHolder
      this.$refs.content.focus(); // Input box gets focus
    },
Copy the code

After the above processing, we have obtained the comment object of our reply.

Handling of comments

<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>
Copy the code

In this case, the input box is bound to a checkComment event, whose logic looks like this when implementing simple comments:

checkComment() {
      if (this.comment_text == "") {
        Toast("Comments can't be empty.");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let to_user_id = ' '; // Because the comment is root, to_user_id and father_comment_id are empty
        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: "Just".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); }); }},Copy the code
  1. Because the comment function we implemented at the beginning is the root comment of the post, there is no reply to who, soto_user_idandfather_comment_idLet’s leave it empty.
  2. Now, what we want to do is reply to user comments. We need to be clear about which user to reply to and which comment to reply to. We already know these two things by clicking on them. Therefore, we need to modify the above logic:
checkComment() {
      if (this.comment_text == "") {
        Toast("Comments can't be empty.");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let to_user_id = ' '; // Because the comment is root, to_user_id and father_comment_id are empty
        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: "Just".nickname: this.userInfo.nickname
        };
----------------------------------------------------
----------------------------------------------------
        if(this.replyUserComment){// If the comment object is not null
            to_user_id = this.replyUserComment.from_user_id; // Redirect the reply object to the commenter
            father_comment_id = this.replyUserComment.id // Make the father_comment_id of the new comment point to the comment ID} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- sendComment({ to_user_id, father_comment_id, comment, video_id }).then(val= > {
            this.comment_text = "";
            this.hasSend = true;
            this.commentList.unshift(newComment); }); }},Copy the code

Render replies in real time

You have now implemented the ability to save replies to the database. But again, it doesn’t render to the page in real time. So, as before, we generate a new comment object and insert it into the array. However, there is a logical difference between the insertion of the reply object and the insertion of the root comment. Let’s take a look at bilibili’s comment graph below:

A reply can also be a comment. In the project, we divided the responses into two categories, one is the primary response and the other is the secondary response.


For comments and replies, the following nested data format is generally used:

{
    avatar:'xxxxxxxxxxxx'.nickname:'xxxxxxxxxxxxx'.comment:'xxxxxxxxxxxxxx'.crete_time:'xxxxxxxxxxxxx'.child_comments:[
        {
             avatar:'xxxxxxxxxxxx'.nickname:'xxxxxxxxxxxxx'.comment:'xxxxxxxxxxxxxx'.crete_time:'xxxxxxxxxxxxx',}... ] }Copy the code

  • For the first level reply, we insert it directly into the header.
  • For the secondary response, we insert directly to the tail. In the previousreplyUserCommentIn the callback function, we do the following:
replyUser(item, index, index2) { 
      item.index = index; // Bind an index attribute to each comment object. This index is used to help us better locate the comment object in the commmentList
      item.index2 = index2; // Index2 is used to help us distinguish the level of reply. -1 indicates that the reply is a root comment, and other values indicate that the reply is from someone else.
      this.replyUserComment = item;//replyUserComment is used to save the current comment object, defined in data
      this.commentPlaceholder = ` reply @${item.nickname}: `;/ / modify the placeHolder
      this.$refs.content.focus(); // Input box gets focus
    },
Copy the code

With the picture above, we can understand it very well. So we can write the following code for the first level reply:

let index = this.replyUserComment.index;
let index2 = this.replyUserComment.index2;
if (this.replyUserComment.index2 == - 1) {
// Insert the first level reply into the head of the child comment
this.commentList[index].child_comments.unshift(newComment);
} else {
// Insert the secondary reply at the end of the child comment
this.commentList[index].child_comments.push(newComment)
}
Copy the code

The complete code

replyUser(item, index, index2) {
      item.index = index;
      item.index2 = index2;
      this.replyUserComment = item;
      this.commentPlaceholder = ` reply @${item.nickname}: `;
      this.$refs.content.focus();
    },
 checkComment() {
      if (this.comment_text == "") {
        Toast("Comments can't be empty.");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        let father_comment_id = ""; // The default parent comment is 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: "Just".nickname: this.userInfo.nickname
        };
        if (this.replyUserComment) {
          // This is not a root comment, but a child comment
          father_comment_id = this.replyUserComment.id; // Make father_comment_id point to this comment
          to_user_id = this.replyUserComment.from_user_id; // make to_user_id point to from_user_id of the parent comment
        }
        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) {
                // Return to level 1
                this.commentList[index].child_comments.unshift(newComment);
              } else {
                // Reply to secondary person
                this.commentList[index].child_comments.push(newComment) } } } ); }},Copy the code

So far, the user’s reply function is also realized, then, it is relatively easy, there is still, the comment function of the like.

To be continued….