Node.js + Express + mongodb 的博客项目之评论系统(十)

前言

本节内容主要是构建一个对博客文章的评论功能,由前端使用 ajax 通过 GET 方式向 /api/comment/post 路由提交评论,服务器再将其保存在数据库中。当用户没有登录时,会提示用户没有登录,不能评论。用户登陆以后,会显示一个评论文本框,用来给用户提交评论,提交后的评论会使用 ajax 进行局部刷新在博客文章的下方显示出来。提交的时候,会在前端进行简单的验证吗,验证通过后才能提交评论,否则 return false。


评论的前端界面

评论的界面,使用模板引擎的条件判断来根据当前用户是否登录来显示不同的界面,也就是使用前面 cookie 的信息来进行判断,若 userInfo.userid 存在则显示评论界面,反之提示未登录。为方便 ajax 获取需要向后端传送的文章 ID ,在这里将文章的 ID 设为一个隐藏的 input 的属性。
在 /views/main/views.ejs 中,在文章内容部分 (<%- contentHtml %>) 后,添加上如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="text-muted text-center">------------本文结束------------</div>
<!-- 评论 -->
<div class="well">
<input type="hidden" id="contentId" value="<%= content.id %>">
<% if (userInfo.userid) {%>
<div class="form-group">
<label for="name">说点什么</label>
<textarea class="form-control" rows="3" cols="4" placeholder="输入评论" id="comment"></textarea>
<br>
<button class="form-control btn btn-primary" id="comment-btn">提交</button>
</div>
<% } else { %>
<div class="alert alert-danger">请先登录!</div>
<% } %>
<div class="commentList">
<div>
<span>作者 | 时间</span>
<p>评论内容</p>
</div>
</div>
</div>


数据库中的评论存储处理

为了方便,我暂时仅将博客的评论新增为文章集合的一个属性,并未新设一个集合。修改 /schemas/contents.js 文件,将博客文章的存储格式新增一个名为 comment 字段,类型为数组,默认为空数组。

1
2
3
4
comment: {
type: Array,
default: []
}

如此一来,博客文章的评论的数据库储存格式也暂时完成。


后端 api 处理

后端关于评论处理的接口主要有两个,一个是提交评论,另一个是读取评论。提交评论是由前端使用 ajax 通过 POST 的方式向服务器提交评论的用户和评论的内容,再由服务器进行相应的格式化处理后存入数据库中。而获取评论同样也是前端使用户 ajax 通过 GET 的方式向服务器提交需要获取评论的文章 ID ,再有服务器将该文章的所有评论从数据库中读取出来后传送给前端,由 ajax 局部刷新加载出来。
在 /routes/api.js 中,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 获取评论的接口
router.get("/comment", (req, res) => {
// 获取提交的信息
let contentId = req.query.contentId || "";

// 根据id查询文章信息
contentModel.findById(contentId, (err, content) => {
if (!err) {
// 向客户端发送当前评论
res.json(content.comment);
return;
} else {
throw err;
return;
}
});
});

// 提交评论的接口
router.post("/comment/post", (req, res) => {
// 获取提交的信息
let contentId = req.body.contentId;
let comment = req.body.comment;

// 构建评论结构
let commentData = {
username: req.userInfo.username,
postTime: new Date(),
content: comment
}

// 根据文章id将文章查询出来
contentModel.findById(contentId, (err, content) => {
if (!err) {
// 如果文章存在则将评论推入
content.comment.push(commentData);
// 保存
content.save();
// 向客户端发送当前评论
res.json(content);
return;
} else {
throw err;
return;
}
});
});


前端 ajax 处理

在 /public/js 文件夹中,新建一个 comment.js 文件用来处理评论相关的 ajax。内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
$(() => {
// 提交评论
(() => {
// 获取提交按钮
$subBtn = $("#comment-btn");
// 获取评论内容
$comment = $("#comment");
// ajax请求
$subBtn.on("click", () => {
// 简单验证
if ($comment.val() === "") {
alert("评论内容不能为空");
return;
}
$.ajax({
type: "post",
url: "/api/comment/post",
data: {
contentId: $("#contentId").val(),
comment: $comment.val()
},
dataType: "json",
success: (result) => {
// 调用渲染评论函数
renderComment();
$comment.val("")
}
});
});
})();

// 渲染评论的函数
renderComment = () => {
// ajax请求
$.ajax({
type: "get",
url: "/api/comment/",
data: {
contentId: $("#contentId").val(),
},
dataType: "json",
success: (result) => {
// 创建html结构
let commentList = "";
for (let i = result.length - 1; i >= 0; i--) {
// 格式化时间
let postTime =
commentList += `
<div>
<span>用户:${ result[i].username } | 时间:${ result[i].postTime }</span>
<p>${ result[i].content }</p>
</div>
`
}
// 添加进入html文档中
$(".commentList").html(commentList);
}
});
}

// 调用渲染评论函数
renderComment();

});


测试

最后再重启服务器,刷新客户端进行测试
评论测试

------ 本文结束 ------

版权声明

Tflin's Blog by Tan Feng Lin is licensed under a Creative Commons BY-NC-ND 4.0 International License.
谭丰林创作并维护的Tflin's Blog博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Tflin's Blog 博客( http://tflin.com ),版权所有,侵权必究。