Дизайн функции комментариев и ответов пользователей [1]

Vue.js

Проект нуждается в анализе:

  1. Откройте всплывающее окно комментариев,inputкоробка получает фокус,inputТекст подсказки по умолчанию в поле:留下你精彩的评论吧, введите содержимое и нажмите提交, вы можете отправить запрос на сервер, и评论内容,评论时间,用户头像,用户昵称Подождите, пока содержимое отобразится на странице.

  2. Нажмите на комментарии пользователей,inputКоробка получает фокус, модифицируйтеinputТекст всплывающей подсказки по умолчанию для поля:回复 @被回复用户的昵称, после нажатия кнопки «Отправить» остальные операции аналогичны1такой же.

  3. Прежде чем пользователи отправят комментарии, они должны пройти проверку.评论内容Не может быть пустым, требуется пользователю登录Комментарии позже.

  4. Кнопка отправки комментария по умолчанию серого цвета и находится вdisableСтатус; когда содержимое комментария не пустое, меняется стиль кнопки отправки, и статус также становитсяenableусловие.

  5. На комментарии можно отвечать и лайкать. Поскольку ответ также можно рассматривать как комментарий, чтобы различать, является ли он комментарием или ответом, мы разработалиfather_comment_id. В то же время, чтобы различать, кому был дан ответ на этот комментарий, мы разработалиto_user_id.

Процесс реализации

1. Реализовать функцию отправки комментариев

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

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

2. Напишите главную страницу

В настоящее время в первую очередь реализована функция отправки комментариев, а отображение комментариев временно отложено. Итак, мы просто имеем дело сinputСтиль и логика коробки. (cssСтиль будет приведен в полном коде в конце статьи. )

 <div class="comment_input_box_hover"></div>
 <div class="comment_input_box" v-show="commentPop"> //commentPop用来控制是否显示评论弹窗
    <input
      :placeholder="commentPlaceholder" //placeholder绑定data中的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> // canSend用来标识评论是否可以发送。
</div>

3. Реализацияdataа такжеmethods

data(){
    commentPlaceholder:'留下你精彩的评论吧',
    comment_text:'', // 评论内容,由v-model实现双向绑定
    hasSend:false, // 标识评论是否已经发送过,防止同一条评论被重复提交
    canSend:false, //canSend用来标识评论是否可以发送
    video_id:'',// 标识是哪一个视频的评论
    to_user_id:'',// 需要回复对象的id
    father_comment_id:'',// 父评论的id
}
methods:{
     // 在发送评论之前,我们需要对输入的内容做合法性判段
     checkComment() {
      if (this.comment_text == "") {
        Toast("评论内容不能为空");
      } 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: "刚刚",
          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){ // 监听comment_text的变化,动态修改提交按钮的样式和状态
        this.canSend = newVal ==='' ? true:false
    }
}

Уведомление,video_idОн получается и присваивается при открытии всплывающего окна комментария, операции открытия и закрытия всплывающего окна комментария здесь не задействованы, поэтому операция присваивания video_id напрямую опущена.

 changeComments(item) {
      if (this.showShareBox) {
        // 打开评论弹窗之前,要先关闭分享弹窗
        this.commentPop = false;
      }
      this.commentPop = true;
      this.video_id = item.id  // 对video_id进行了赋值操作
      // 打开评论窗时需要从服务端获取评论列表
      getCommentList(this.video_id).then(val => {
        let data = val.data.message;
        data.forEach(item => {
        });
        this.commentList = data;
      });
    },

Отображение комментариев

1. Напишите главную страницу

  <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)" <!-- 在这里为每条评论绑定了点击事件-->
                >
                  <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"
                            >
                              回复
                              {{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">暂无评论</div>
            </div>
          </ul>
        </div>
      </van-popup>

Получить отзывы

При открытии всплывающего окна комментария инициируйте запрос на получение комментария

methods:{
    changeComments(item) {
      if (this.showShareBox) {
        // 打开评论弹窗之前,要先关闭分享弹窗
        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))
        })
      });
    },
}

отображение эффекта страницы

Вставка комментариев в реальном времени

Во фронте реализована функция комментариев, но вновь размещенные комментарии не отображаются на странице, только после обновления страницы. Чтобы решить эту проблему, нам нужно инкапсулировать новый комментарий в объект после отправки комментария, а затем вставить его вcommentListсередина. Новые комментарии располагаются впереди, то есть новые комментарии должны располагаться на первой позиции. Таким образом, новые комментарии должны быть вставлены вcommentListв положении 0.

Как создать новый объект комментария
Когда страница отображается, содержимое, которое необходимо отобразить,nickname,avatar,comment,create_time, кроме того, поскольку в процессе обхода используетсяitem.idсвязывать:keyиз. Итак, нам нужно связатьid, на самом деле этоidОн играет только временную роль и не будет записан в базу данных. Чтобы обеспечить уникальность идентификатора, мы передаемDate.now()чтобы сгенерировать этоid. А содержимое других полей мы можем передатьvuexили взято из контекста.
Так построеноcommentЭто выглядит так:

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

Кроме того, нам нужно изменить нашsendCommentЛогика после этого состоит в том, чтобы вставить новый объект комментария вcommentListвходить.

 sendComment({ to_user_id, father_comment_id, comment, video_id }).then(
          val => {
            this.comment_text = "";
            this.hasSend = true;
            this.commentList.unshift(newComment) //将新的评论对象插入到数组中去
          }
        );

отображение эффекта страницы

vueРеализована функция комментариев во фронтальной части, а следующим шагом является функция ответа...