上期文章完成了博客详情的目录导航,接下来完成博客评论的发布和展示
需求: 一篇博客下可能有多条评论,一条评论下也可能有多条评论。评论只是分为一级评论和二级评论,一级评论下有多条二级评论,二级评论之间可以相互回复,如aa回复bb,bb回复cc。
思路:
- 在数据库中给评论表添加parentId字段记录父评论id,用于在二级评论中展示谁评论谁;rootParentId字段,用于给二级评论匹配一级评论
- 后端的评论类除了增加以上两个字段外,还增加一个child字段用于保存该评论的二级评论,一个静态方法,该方法返回一个一级评论数组,并将属于该一级评论的二级评论数组,放入child中
- 前端获取博客评论后渲染一级评论和二级评论
后端
comment类增加的属性和方法
private Integer parentId; // 父评论ID(被回复的评论)
private Integer rootParentId; // 根评论ID(最顶级的评论)
private Map<Integer, Comment> child; // 本评论下的子评论
/**
* 构建评论树
* @param list
* @return
*/
public static List<Comment> processComments(List<Comment> list) {
Map<Integer, Comment> map = new HashMap<>(); // (id, Comment)
List<Comment> result = new ArrayList<>();
// 将所有根评论加入 map
for(Comment comment : list) {
if(comment.getRootParentId() == null)
result.add(comment);
map.put(comment.getCommentId(), comment);
}
// 子评论加入到父评论的 child 中
for(Comment comment : list) {
Integer id = comment.getRootParentId();
if(id != null) { // 当前评论为子评论
Comment p = map.get(id);
if(p.getChild() == null) {
// child 为空,则创建
p.setChild(new HashMap<>());
}
p.getChild().put(comment.getCommentId(), comment);
System.out.println("%%%****");
System.out.println(p);
}
}
return result;
}
前端
前端获得的数据如下
渲染一级评论和二级评论
<div class="myborder" v-for="comment in commentList ">
<span>{{ comment["commentId"] }}</span>
<span>{{ comment["commentContent"] }}</span>
<span>{{ comment["userName"] }}</span>
<template v-if="comment.child != null">
<div v-for="(childComment) in comment.child">
<span>
{{ childComment.commentId }}
{{ childComment.commentContent }}
{{ childComment.userName }}
</span>
<template v-if="typeof comment.child[childComment.parentId] == 'object'">
<span> 回复{{ comment.child[childComment.parentId].userName }}</span>
</template>
</div>
</template>
</div>
样式还没写好,大致效果如下