记录:
- 最近在整一个博客系统,看了demo 的前端发现他并没有实现多级评论,但这个其实还是蛮常见的,于是就想自己实现一下,想了好久,查了一些资料,终于搞出来了,整了一个小 demo,现在记录一下
后台
后台就是通过树来实现。
通过数据库的表来构建一个树。
package com.ekin.blog.common.utils;
import cn.ekin.blog.po.entity.CommentInfo;
import cn.ekin.blog.common.domain.Node;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: ekin
* @Date: 2021/6/14 10:21
*/
public class TreeUtil {
// 把评论信息的集合转化为一个树
public Node buildTree(List<CommentInfo> commentInfo, long id){
Node tree = new Node();
List<Node> children = new ArrayList<>();
List<Node> nodeList = new ArrayList<>();
for (CommentInfo info : commentInfo) {
children.add(buildNode(info));
}
tree.setId(id);
tree.setChildren(children);
for (Node child : children) {
Node node = findNode(children, child.getParentId());
List<Node> nodes = new ArrayList<>();
if (node != null) {
if (node.getChildren() != null) {
nodes = node.getChildren();
nodes.add(child);
node.setChildren(nodes);
}else {
nodes.add(child);
node.setChildren(nodes);
}
nodeList.add(child);
}
}
for (Node node : nodeList) {
children.remove(node);
}
return tree;
}
private Node findNode(List<Node> nodes, long id){
for (Node node : nodes) {
if (node.getId() == id) {
return node;
}
}
return null;
}
private Node buildNode(CommentInfo info){
Node node = new Node();
node.setId(info.getId());
node.setParentId(info.getParentId());
node.setObject(info);
node.setChildren(null);
return node;
}
}
前端
前端是用的 elementUI 和 Vue,不得不说作为一个后端狗写前端真是太折磨了…
CSS:
<div class="comment" v-for="articleComment in articleCommentTree.children" :key="articleComment.object.id">
<a class="avatar">
<img :src="imgSrc" alt="头像">
</a>
<div class="content">
<a class="author">{{articleComment.object.name}}</a>
<div class="metadata">
<span class="date">{{articleComment.object.createByStr}}</span>
</div>
<div class="text">{{articleComment.object.content}} </div>
<div class="actions">
<a class="reply">回复</a>
</div>
</div>
<div v-if="articleComment.children != null" class="comments">
<div class="comment" v-for="subArticleComment in children" :key="subArticleComment.object.id">
<a class="avatar">
<img :src="imgSrc" alt="头像">
</a>
<div class="content">
<a class="author">{{subArticleComment.object.name}}</a>
<div class="metadata">
<span class="date">{{subArticleComment.object.createByStr}}</span>
</div>
<div class="text">{{subArticleComment.object.content}} </div>
<div class="actions">
<a class="reply">回复</a>
</div>
</div>
</div>
</div>
</div>
到这里也只是一个静态页面,也只能实现到二级评论。那么如何实现多级评论呢?
可以用 vue 的递归来实现。
将多级评论封装为一个组件
<template>
<div class="multistage">
<div v-if="children != null" class="comments">
<div class="comment" v-for="subArticleComment in children" :key="subArticleComment.object.id">
<a class="avatar">
<img :src="imgSrc" alt="头像">
</a>
<div class="content">
<a class="author">{{subArticleComment.object.name}}</a>
<div class="metadata">
<span class="date">{{subArticleComment.object.createByStr}}</span>
</div>
<div class="text">{{subArticleComment.object.content}} </div>
<div class="actions">
<a class="reply">回复</a>
</div>
</div>
<multistage :children="subArticleComment.children"/>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'multistage',
props: ['children'],
data () {
return {
imgSrc: 'https://www.static.talkxj.com/avatar/user.png'
}
}
}
</script>
<style scoped>
</style>
调用
<div class="comment" v-for="articleComment in articleCommentTree.children" :key="articleComment.object.id">
<a class="avatar">
<img :src="imgSrc" alt="头像">
</a>
<div class="content">
<a class="author">{{articleComment.object.name}}</a>
<div class="metadata">
<span class="date">{{articleComment.object.createByStr}}</span>
</div>
<div class="text">{{articleComment.object.content}} </div>
<div class="actions">
<a class="reply">回复</a>
</div>
</div>
<multistage :children="articleComment.children"/>
</div>
到这里就OK了!