Project demand analysis:

  1. Open the comment popup, input box to get the focus, input box default prompt text to leave your wonderful comments, input content click submit, you can send a request to the server, and the comment content, comment time, user profile picture, user nickname and other content in the page rendering.

  2. Click user comment, input box to get the focus, modify the default prompt text of input box to reply @ the nickname of the user to be replied, click Submit, the remaining operations are the same as 1.

  3. Before submitting a comment, users need to verify that the comment content cannot be empty. Users need to log in to the system to comment.

  4. The comment submit button is grayed out and disabled by default; When the comment content is not empty, the submit button style changes and the status changes to Enable.

  5. Comments can be replied to and liked. Since a comment can also be considered a comment, to distinguish between a comment and a reply, we’ve created father_comment_id for the comment object. Also, to_user_id is designed for the comment object in order to distinguish who the comment is responding to.

The implementation process

1. Implement the function to send comments

import axios from 'axios'
import {BASE_URL} from './route'

export function sendComment(params){
  return axios.post(`${BASE_URL}/saveComment`,params)
}
Copy the code

2. Write front-end pages

At present, the function of sending comments is implemented first, and the display of comments is temporarily put aside. So, we just have to deal with the style and logic of the input box. (CSS styles are given in full code at the end of the article.)

 <div class="comment_input_box_hover"></div>
 <div class="comment_input_box" v-show="commentPop"> //commentPop controls whether to display comments pop-ups
    <input
      :placeholder="commentPlaceholder" //placeholder binding data, commentPlaceHolder, to meet our requirements
      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>// canSend is used to indicate whether a comment can be sent.</div>
Copy the code

3. Implement relevancydataandmethods

data(){
    commentPlaceholder:'Leave a comment.', comment_text:' '.// Comment content is bidirectional bound by V-Model
    hasSend:false.// Identify whether a comment has already been sent to prevent the same comment from being submitted twice
    canSend:false.//canSend is used to indicate whether a comment can be sent
    video_id:' '.// The logo is a comment on which video
    to_user_id:' '.// The id of the object to reply to
    father_comment_id:' '.// The parent comment id
}
methods:{
     // Before sending a comment, we need to validate the input
     checkComment() {
      if (this.comment_text == "") {
        Toast("Comments can't be empty.");
      } else {
        if (!this.isLogin) {
          this.$router.push({
            path: "/login"
          });
          return;
        }
        const to_user_id = this.to_user_id;
        const father_comment_id = this.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); }); } }, } watch:{ comment_text(newVal,oldVal){// Listen for changes in comment_text to dynamically modify the style and state of the submit button
        this.canSend = newVal ===' ' ? true:false}}Copy the code

Pay attention to,video_idIt is obtained and assigned when the comment popover is opened. The opening and closing of the comment popover are not involved here, so the assignment of video_id is directly omitted

 changeComments(item) {
      if (this.showShareBox) {
        // Close the Share popup before opening the comments popup
        this.commentPop = false;
      }
      this.commentPop = true;
      this.video_id = item.id  // Assign to video_id
      // To open the comment window, you need to get the comment list from the server
      getCommentList(this.video_id).then(val= > {
        let data = val.data.message;
        data.forEach(item= >{});this.commentList = data;
      });
    },
Copy the code

Comments show

1. Write front-end pages

<van-popup v-model="commentPop" :overlay="true" class="comment_container" position="bottom"> <div class="comment_box"> <div class="comment_top"> {{commentlist. length}} 查 看 < I class="iconfont icon-guanbi1 guanbi3" @click="closeCommentsBox" >&#xe647; </i> </div> <ul class="comment_ul"> <div v-if="commentList.length! =0"> <transition-group appear> <li class="comment_li" v-for="(item,index) in commentList" :key="item.id" @click="replyUser(item,index,-1)" <! -- Here bind the click event for each comment --> > <div class="comment_author_left"> <img: SRC ="item.avatar" /> </div> <div class="comment_author_right"> <div class="comment_author_top"> <div class="comment_author_name">@{{item.nickname}}</div>  <div class="icon-shoucang1_box" @click.stop="commentLove(item,index,-1)"> <div class="icon_right_change" :class="item.love_comment? 'love_active':''"> <i class="iconfont icon-shoucang1"></i> </div> <div class="shoucang1_num">{{item.love_count}}</div> </div> </div> <div class="comment_author_text"> {{item.comment}} <span>{{item.create_time}}</span> </div> </div> <div class="clear"></div> <div class="comment_reply_box"> <transition-group appear> <div class="comment_reply_li" v-for="(item2,index2) in item.child_comment" :key="item2" @click.stop="replyUser(item2,index,index2)" > <div class="comment_reply_left"> <img :src="item2.avatar" /> </div> <div class="comment_reply_right"> <div class="comment_reply_top"> <div class="comment_reply_name">@{{item2.nickname}}</div> <div class="icon-shoucang1_box" @click.stop="commentLove(item2,index,index2)" > <div class="icon_right_change" :class="item2.love_comment?'love_active':''" > <i class="iconfont icon-shoucang1"></i> </div> <div class="shoucang1_num">{{item2.love_count}}</div> </div> </div> <div class="comment_reply_text"> <span v-if="item.user_id! =item2.be_commented_user_id && item.user_id! =item2.user_id" > reply {{item2.be_commented_nickname}} :  </span> {{item2.comment_content}} <span>{{item2.create_time}}</span> </div> </div> <div class="clear"></div> </div> </transition-group> </div> </li> </transition-group> </div> <div class="no_message" v-if="! Commentlist. length"> < I class="iconfont iconfont_style icon-zanwupinglun"></ I >< div class="no_message_tips"> no comments </div> </div> </ul> </div> </van-popup>Copy the code

Get comments

Initiate a request to get a comment when the comment popover opens

methods:{
    changeComments(item) {
      if (this.showShareBox) {
        // Close the Share popup before opening the comments popup
        this.commentPop = false;
      }
      this.commentPop = true;
      this.video_id = item.id
      getCommentList(this.video_id).then(val= > {
        this.commentList = val.data.message;
        this.commentList.forEach((item) = >{
          item.create_time = formatTime(new Date(item.create_time)) }) }); }},Copy the code

Page effect display

Implement real-time comment insertion

Previously, comments have been implemented, but newly posted comments are not displayed on the page, only when the page is refreshed. To fix this, we need to wrap the new comment into an object after sending it and insert it into the commentList. New comments should be placed first. So new comments should be inserted at position 0 in the commentList.

How to build the new comment object The page display, need to display the contents of the nickname, avatar, comment, create_time, in addition, because in the process of traverse is the use of the item. The id to bind: key. Therefore, we need to bind an ID to this object, which is only temporary and will not be written to the database. To keep the id unique, we generate the ID with date.now (). The contents of other fields can be retrieved in vuex or context. So the constructed comment looks like this:

const id = Date.now()
const comment = this.comment_text;
const newComment = {
  avatar:this.userInfo.avatar,
  comment,
  id,
  create_time:'just'.nickname:this.userInfo.nickname,
}
Copy the code

In addition, the logic after sendComment needs to be modified to insert the new comment object into the commentList.

 sendComment({ to_user_id, father_comment_id, comment, video_id }).then(
          val= > {
            this.comment_text = "";
            this.hasSend = true;
            this.commentList.unshift(newComment) // Insert the new comment object into the array});Copy the code

Page effect display

Comments have been implemented in the front end of vue, and the next step is the reply function…