在前面,咱们已是实现了用户评论功能以及评论的实时显示,如今,咱们来实现一下,用户的回复功能。实现效果以下所示:
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)
}
}
}
);
}
},
复制代码
到目前为止,用户的回复功能也是实现了,接下来,就相对轻松了,还剩下,评论功能的点赞。
未完待续....