最近在写博客功能中的无限评论,比如知乎上的,我可以给根评论进行评论,也可以给子评论进行评论,下面是我做的一个简单的例子,分享给大家,希望能帮助各位,也希望可以指出缺点。
先上图,看功能

思路:
- 点击文章,获取文章的id,例如id为1
- 点击以后,查找文章id为1的全部评论,进行遍历(这里用到的是递归,方便观看,如上述,黄的为根评论,回复的是文章;绿的为子评论,回复的是根评论或者是其他子评论)
- 一开始刚发布文章肯定没有评论,所以,在最下面是发布评论,是对文章进行评论,使其有根评论,获取其根评论的id。
- 在有了根评论后,点击根评论后面的回复按钮,弹出一个回复的div,填写姓名和内容
- 点击弹出div的回复,将回复的信息添加到数据库,在进行2步骤,重新遍历;
- 点击子评论,同样可以出现回复的div,添加姓名和内容,点击回复按钮,在进行2步骤,遍历。
- 这样的缺点:遍历的话,消耗性能比较大(但我就想出来这一种,建议各位可以看看闭包表,这种评论相当于树结构,方便查找,但我脑子笨,没咋看明白)
评论表:

前端页面:
页面比较丑,我只是说功能,大家可以自己去写。
1 //这个是回复的div 2 <div class="response_div"></div>

这个是在js里动态生成的,只是有个父元素去装其他子元素
//评论的div,装根评论和子评论
评论:
<div class="user_comments"></div>
//发表评论的div,为根评论 发表评论
<div>
<form id="form" onsubmit="return false" action="###" method="post">
<input id="article_id" type="hidden" name="articleId" value="${requestScope.article.get("ArticleId")}" >
<p>个人昵称:<input id="user_name" type="text" name="name"></p>
<p> 通知邮箱:<input id="email" type="email" name="email"></p>
<p>评论内容:<input id="content" type="text" name="content"></p>
<input type="button" value="提交" onclick="ajaxSelectComment()">
</form>
</div>

其他相关在js文件中:
首先文章里没有评论,那么我在发表评论以后,点击按钮,将评论的信息通过ajax提交到servlet中(这里一开始打算用form表单的action方法直接提交,但后来感觉用ajax好一些,个人想法)
//发表评论,先获取输入框的内容,将值作为参数传递给servlet,然后返回所有的评论
function ajaxSelectComment() {
let articleId=$("#article_id").val();
let name=$("#user_name").val();
let email=$("#email").val();
let content=$("#content").val();
$.ajax({
url:"article?action=addComment",
type:"POST",
dataType: "json",
data:{articleId,name,email,content},
success:function (result) {
alert("提交成功");
console.log(result);
showRootComment(result);
},
error:function () {
alert("请求失败");
}
});
}

请求后,跳到servlet中
protected void addComment(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取对应文章的id,评论的姓名,内容,以及email
Map<String, String[]> comment = req.getParameterMap();//声明service层对象ArticleService articleService= new ArticleServicesImpl();//调用service层中的方法articleService.addComment(Integer.parseInt(comment.get("articleId")[0]),comment.get("name")[0],comment.get("content")[0],comment.get("email")[0]);//调用查询全部评论的方法,并将其转换成json格式(这里我将查询全部评论和转成JSON格式封装成了一个方法)this.returnJson(resp,this.selectUserComment(comment)); }//查询全部评论方法,将Map传入其中,然后获取对应文章的id
public List<Comment> selectUserComment(Map<String, String[]> parameterMap){ ArticleService articleService=new ArticleServicesImpl(); return articleService.selectComment(Integer.parseInt(parameterMap.get("articleId")[0]));}//将集合转成JSON格式
public void returnJson(HttpServletResponse resp ,Object object) throws ServletException, IOException{ //将传过来的数组转化为JSON PrintWriter out = resp.getWriter(); Gson gson=new Gson(); String jsonComments = gson.toJson(object);//查找总的评论并且转化为数组 System.out.println(jsonComments); out.write(jsonComments); out.flush(); out.close();}

showRootComment(result)方法:
function showRootComment(result){
let str="";
console.log(result);
$(".user_comments").empty();
for (let i = 0; i <result.length ; i++) {
console.log(result.length);
if(result[i].responseId==0){//说明这个是根评论
str="<div class='rootResponse'>\n" +"<input type='hidden' name='commentId' value="+result[i].pid+">"+
"#"+i+"楼"+"评论时间:"+result[i].publishTime + " | " + result[i].commentName+" <button onclick='responseDiv($(this).prev().val(),$(this).prev())'>回复<button/>\n" +
"<div>"+result[i].commentContent+ "</div>\n" +
"</div><hr>";
$(".user_comments").append(str);
//查询子评论
digui(result,result[i]);
}
}
}
查询子评论方法:digui(result,result[i])
function digui(result,comment) {
let str='';
console.log(result+"###"+comment);
for (let i = 0; i <result.length ; i++) {
console.log(comment.pid);
if (result[i].responseId==comment.pid){//那么这个是评论的子id
str="<div class='ziResponse'>\n" +"<input type='hidden' name='commentId' value="+result[i].pid+">"+
"评论时间:"+result[i].publishTime + " | " + result[i].commentName+"<button onclick='responseDiv($(this).prev().val(),$(this).prev())'>111回复<button/>\n" +
"<div>"+result[i].commentContent+ "</div>\n" +
"</div><hr>";
//将其子评论div添加到.user_comments div中
$(".user_comments").append(str); console.log(str); digui(result,result[i]); } } }
最后一行递归的作用:在查找到第一个子评论后,查找是否有其他子评论回复当前的子评论,如果有,则继续遍历,如果没有,则跳过
到这的话,遍历的就ok了,下面我们看如何回复评论而不是回复文章
每次遍历,都会有一个回复的按钮
<button onclick='responseDiv($(this).prev().val(),$(this).prev())'>111回复<button/>
点击回复按钮,
$(this).prev().val()
为获取当前元素的同胞元素的值,获取其对应的评论的id
$(this).prev()获取其对应的同胞元素点击回复按钮,跳到 responseDiv($(this).prev().val(),$(this).prev())方法
function responseDiv(responseId,nowElement) {//首先将.responsediv移除,因为在点击其他评论的回复时,其他评论的回复div将消失
$(".response").remove();
let str="<div class=\"response\">\n" +
" <input type=\"text\" name=\"userName\" placeholder=\"请输入用户姓名\" id=\"user_comment_name\">\n" +
" <input type=\"text\" name=\"userComment\" placeholder=\"请输入评论内容\" id=\"user_comment\">\n" +
" <input type=\"button\" value=\"回复\" onclick=\"ajaxResponse("+responseId+")\">\n" +
" </div>";
//将这个回复div添加进这个评论的div中
nowElement.parent().append(str);
}
点击回复,跳到ajaxResponse方法中,找到回复responseId,
function ajaxResponse(responseId) {
//点击回复后,将回复的div移除
$(this).prev().remove();
//获取回复对应的文章id,回复的姓名,回复的内容
let articleId=$("#article_id").val();
let name=$("#user_comment_name").val();
let content=$("#user_comment").val();
$.ajax({
url:"article?action=addUserComment",
type:"POST",
dataType: "json",
data:{articleId,name,content,responseId},
success:function (result) {
alert("提交回复成功");
//重新遍历
showRootComment(result);
},
error:function () {
alert("请求失败");
}
});
}///
servlet添加子评论的方法
protected void addUserComment(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String, String[]> userComment = req.getParameterMap();
articleService.addResponse(Integer.parseInt(userComment.get("articleId")[0]),userComment.get("name")[0],userComment.get("content")[0],Integer.parseInt(userComment.get("responseId")[0]));
this.returnJson(resp,this.selectUserComment(userComment));
}
添加回复,首先出现一个回复的div,填写回复的信息,点击回复按钮,将回复的内容添加到数据库,然后返回所有的评论,继续遍历,思路基本上就是这样
service层方法:
/**
* 添加的是根评论
* @param articleId
* @param name
* @param content
* @param email
*/
@Override
public void addComment(int articleId, String name, String content, String email) {
articleDao.addComment(articleId,name,content,email);
//先查找对应文章的评论有多少
long commentSum=articleDao.selectCommentsSum(articleId);
//修改对应文章中评论的数量
articleDao.insertCommentsSum(commentSum,articleId);
}
/**
* 查找对应文章的评论
* @param articleId
* @return
*/
@Override
public List<Comment> selectComment(int articleId) {
return articleDao.selectComment(articleId);
}
/**
* 添加对应文章的评论,子评论
* @param articleId
* @param commentName
* @param commentContent
* @param responseId
*/
@Override
public void addResponse(int articleId,String commentName,String commentContent,int responseId) {
articleDao.addUserComment( articleId, commentName, commentContent,responseId);
}
dao层方法:
/**
*查找对应文章的全部评论
*/
public List<Comment> selectComment(int articleId) {
List<Comment> comments=null;
String sql= "SELECT * FROM COMMENT WHERE Article_Id=?";
try {
comments = queryRunner.query(sql, new BeanListHandler<Comment>(Comment.class), articleId);
} catch (SQLException e) {
e.printStackTrace();
}
return comments;
}
/**
* 添加根评论
* @param articleId
* @param name
* @param content
* @param email
*/
@Override
public void addComment(int articleId, String name, String content, String email) {
String sql="INSERT INTO COMMENT (Article_Id,CommentName,CommentContent,email) VALUES(?,?,?,?) ";
Object[] parms={articleId,name,content,email};
try {
queryRunner.update(sql,parms);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 添加子评论
* @param articleId
* @param commentName
* @param commentContent
* @param responseId
*/
@Override
public void addUserComment(int articleId,String commentName,String commentContent,int responseId) {
String sql="INSERT INTO COMMENT (Article_Id,CommentName,CommentContent,ResponseId) VALUES(?,?,?,?)";
Object[] parms={articleId,commentName,commentContent,responseId};
try {
queryRunner.update(sql,parms);
} catch (SQLException e) {
e.printStackTrace();
}
}
这就是关于评论的所有操作,如果大家有疑惑或者更好的建议,在评论区留言,看到会立即回复!
来源:https://www.cnblogs.com/BLACKJT/p/12630096.html