前期设计思想 ,首先要知道评论和评论是多对多关系,那麽必然就需要一个中间表来关联表和表之间的关系。
效果图:
mysql数据库设计
--评论表
CREATE TABLE `c_comment` (
`cid` varchar(255) NOT NULL COMMENT '评论id',
`bid` int(1) NOT NULL COMMENT '存储文章id',
`id` varchar(255) NOT NULL COMMENT '评论人',
`datetime` varchar(255) NOT NULL COMMENT '评论时间',
`container` varchar(255) NOT NULL COMMENT '评论内容',
`replyOne` varchar(255) DEFAULT NULL COMMENT '回复评论对象的昵称',
PRIMARY KEY (`cid`),
KEY `bid` (`bid`),
KEY `id` (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
中间表设计
CREATE TABLE `c_comment_id` (
`bid` int(1) NOT NULL COMMENT '博客的id',
`cid1` varchar(255) NOT NULL COMMENT '一级评论的id',
`cid2` varchar(255) NOT NULL COMMENT '二级评论的id',
KEY `bid` (`bid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
评论查询实现根据博客bid查出本篇博客的全部评论,然后再根据博客bid将关联表中数据查询出来。
然后通过 axios 异步加载 执行多个并发请求
将数据加载到前端,然后在编写js算法将两个返回结果合并重新构造数据结构,完成效果。
后端代码就省略了, 看下sql语句
//博客bid查出本篇博客的全部评论
select c.*,u.blogAvator,u.anonymous from c_comment c,c_user_detail u where c.id = u.id and c.bid=#{bid} order by c.datetime desc
//根据博客bid查询关联表中数据
select * from c_comment_id where bid=#{bid}
这两个sql语句非常简单,我尝试采用一对多的方法将数据全部查询出来但是评论数据全在一张表上是在想不出来,有大佬知道的在评论区赐教一下
//html骨架
<!-- betterscroll 滚动插件-->
<BScrollWrapper>
<div slot="BScroll">
<div class="input_comment">
<img :src="auth.userdetail.blogAvator" alt="blog头像" class="avatar">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="textarea"
maxlength="200"
:rows="rows"
show-word-limit
>
</el-input>
</div>
<div class="button_submit">
<span class="animated fadeIn" style="color: red;display: none;">请先输入评论内容! </span>
<el-button size="mini" @click="_handleSuPing($event)">速评一下</el-button>
<el-button type="primary" size="mini" @click="_handleSubmit">发表评论</el-button>
</div>
<!---------------------评论列表区------------------------>
<!--一级评论区-->
<ul class="comment-list_one">
<li class="border-bottom" v-for="(item,index) of commentData" :key="index">
<!--数据展示区-->
<comment-data :Item="item"></comment-data>
<!--二级评论区-->
<ul class="comment-list_two">
<li v-for="(item1,index1) of item.datalist" v-if="item.datalist.length!=0" :key="index1">
<!--数据展示区-->
<comment-data :Item="item1"></comment-data>
</li>
</ul>
</li>
</ul>
</div>
</BScrollWrapper>
重点js算法
getBlogComment() {
axios.all([axios.get(`/api/blog/comment/${this.getBlogData.bid}`), axios.get(`/api/blog/commentid/${this.getBlogData.bid}`)]).then(axios.spread((res1, res2) => {
this.$nextTick(() => {
//所有评论列表
let data1 = res1.data;
//相互评论的关联表
let data2 = res2.data;
//将这两个数据合并重新构造列表
this.commentData = data1.reduce((prev, item, index, obj) => {
//根据关联表进行判断 那些是相互评论的
let cid = data2.filter((item1) => {
return item1.cid1 == item.cid;
});
//得出总的评论数
let len = cid.length;
this.total += len == 0 ? 0 : len + 1;
//cid不为空说明存在二级评论
if (len != 0) {
let datalist = [];
//将cid遍历获得 一级评论下的子评论
cid.forEach((item2) => {
//得到子评论数据
let data3 = obj.find((item3) => {
return item3.cid == item2.cid2;
});
//将一级评论cid赋值给子id
data3.cid = item.cid;
// 加入列表
datalist.push(data3);
});
// 构造数据格式
prev.push({
bid: item.bid,
cid: item.cid,
id: item.id,
datetime: item.datetime,
container: item.container,
userDetail: {
anonymous: item.userDetail.anonymous,
blogAvator: item.userDetail.blogAvator
},
datalist: datalist.sort((a, b) => {
return new Date(b.datetime) - new Date(a.datetime)
})
})
} else if (item.replyOne == "") {
prev.push({
bid: item.bid,
cid: item.cid,
id: item.id,
datetime: item.datetime,
container: item.container,
userDetail: {
anonymous: item.userDetail.anonymous,
blogAvator: item.userDetail.blogAvator
},
datalist: []
})
}
return prev;
}, []);
});
}))
},
最后合并完的数据结构