用戶評論及回覆功能設計[一]

項目需求分析:

  1. 打開評論彈窗,input框獲取焦點,input框默認提示文字爲留下你精彩的評論吧,輸入內容點擊提交,便可向服務器發送請求,並將評論內容,評論時間,用戶頭像,用戶暱稱等內容在頁面進行渲染。javascript

  2. 點擊用戶評論,input框獲取焦點,修改input框的默認提示文字爲回覆 @被回覆用戶的暱稱,點擊提交後,剩餘操做與1相同。css

  3. 用戶提交評論前,須要作校驗,評論內容不能爲空,用戶須要登陸後才能評論。html

  4. 評論提交按鈕默認是灰色,處於disable狀態;當評論內容不爲空時,提交按鈕樣式發生變化,狀態也變爲enable狀態。前端

  5. 評論是能夠被回覆和點讚的。由於回覆也能夠看作是一條評論,爲了區別是評論仍是回覆,咱們爲評論對象設計了father_comment_id。同時,爲了區分這個評論是回覆誰的,咱們爲評論對象設計了to_user_idvue

實現流程

1.實現發送評論的函數

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

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

2.編寫前端頁面

目前先實現評論發送功能,對評論展現暫時先放在一邊。因此,咱們只要處理input框的樣式和邏輯。(css樣式會在文章最後完整代碼給出。)java

<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.實現相關datamethods

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的賦值操做ios

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>
複製代碼

獲取評論

打開評論彈窗時,發起獲取評論的請求vuex

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只是起臨時做用,並不會寫到數據庫。爲了保證id的惟一性,咱們經過Date.now()來生成這個id。而其餘字段的內容,咱們能夠經過在vuex中,或者上下文中取到。
因此構建出來的comment長成下面這個樣子:axios

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前端部分的評論功能已經實現,接下來就是回覆功能了...

相關文章
相關標籤/搜索