在前面,咱們已是實現了用戶評論功能以及評論的實時顯示,如今,咱們來實現一下,用戶的回覆功能。實現效果以下所示:
javascript
咱們梳理一下評論回覆流程:html
input
框獲取焦點,input
框的placeholder
變爲回覆 @nickname
細心的同窗可能會發現,當回覆成功後,頂部的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':''"></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);
}
);
}
},
複製代碼
to_user_id
和father_comment_id
咱們置空。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)
}
}
}
);
}
},
複製代碼
到目前爲止,用戶的回覆功能也是實現了,接下來,就相對輕鬆了,還剩下,評論功能的點贊。
未完待續....