几天我们来实现博客详情页的评论功能.
进过前两发的讲解, 我们已经对新增feature的实现流程轻车熟路了.首先我们在momdel文件夹新建comment.js. 然后我们分析一下comment字段的组成, 很明显, 一个评论需要有评论内容, 发布评论的用户名(也就是当前登陆的用户). 然后,不要忘了在模型post里面添加comment字段, 储存该片文章的所有评论.
等等..
我们还有一个问题没解决, 那就是用户在发起comment的post请求的时候, 我们还要知道插入倒哪篇文章的comment字段数组里面啊.所以, 在post请求中还要传递评论的博客的名字, 作者, 时间, 以此来查找相应的博客.
基于以上分析, 我们不难写出下面的代码.
var mongodb = require('./database');
function Comment(postAuthor, postTitle, postTime, userName, commentContent, replyUserName) {
this.postAuthor = postAuthor;
this.postTitle = postTitle;
this.postTime = postTime;
this.userName = userName;
this.commentContent = commentContent;
this.replyUserName = replyUserName;
}
module.exports = Comment;
Comment.prototype.save = function(callback) {
var date = new Date();
var postDoc = {
'author': this.postAuthor,
'title': this.postTitle,
'time.till_minute': this.postTime
},
time = {
date: date,
till_year: date.getFullYear(),
till_month: date.getFullYear() + '-' + (date.getMonth() + 1),
till_day: date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(),
till_minute: date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + '-' + date.getHours() + ':'
+ (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() )
},
comment = {
userName: this.userName,
commentTime: time.till_day,
commentContent: this.commentContent,
replyUserName: this.replyUserName
};
console.dir(comment);
mongodb.get().collection('posts', function(err, collection) {
if (err) {
mongodb.close();
callback(err);
}
collection.update(postDoc, {$push: {'comments': comment}}, function(err, post) {
// console.log(post);
mongodb.close();
if (err) {
return callback(err);
}
callback(null);
});
});
};
然后打开post.js更改成下面的样子:
var post = {
title: this.title,
author: this.author,
content: this.content,
time: time,
comments: [],
};
记下来我们打开index.js添加发布comment的路由.
app.use('/comment', comment);
同理在routes文件夹新建一个comment.js文件, 写入一下代码:
var Comment = require('comment');
var express = require('express');
var router = express.Router();
router.post('/', function(req, res) {
var crtUser = req.session.user;
var comment = new Comment(req.body.postAuthor, req.body.postTitle, req.body.postTime, crtUser.name, req.body.commentContent, req.body.replyUserName);
(req.body.replyUserName);
comment.save(function(err) {
if (err) {
req.flash('error', err);
res.redirect('back');
}
req.flash('success', '发表评论成功');
res.redirect('back');
});
})
module.exports = router;
最后一步, 打开/views/article.ejs, 在article.article-wrapper下面添加一下代码
<div class="comment-wrapper">
<div class="comment-list">
<% if (post.comments != null ) { post.comments.forEach(function(comment, index){ %>
<div class="comment-item">
<a class="user-img">
<img src="/images/hacker.png" alt="" />
</a>
<div class="comment-right">
<a href="/u/<%= user.name%>" class="link comment-post-user"><%= comment.userName%></a>
<p class="comment-content">
<span><%= comment.replyUserName%></span>
<%= comment.commentContent%>
</p>
<div class="commentTime">
<span class="comment-post-time"><%= comment.commentTime%></span>
<span class="reply link" data-user-name="<%= comment.userName%>" data-comment-id="<%= index%>">reply</span>
</div>
</div>
</div>
<% })}%>
</div>
</div>
<% if(user) {%>
<div class="comment-input-wrapper">
<form class="comment-input" action="/comment" method="post">
<div class="form-wrapper">
<input type="hidden" name="postAuthor" value="<%= post.author %>">
<input type="hidden" name="postTitle" value="<%= post.title %>">
<input type="hidden" name="postTime" value="<%= post.time.till_minute %>">
<textarea name="commentContent" rows="8" cols="40" placeholder="牛逼的你, 来评论一发吧" class="textarea"></textarea>
</div>
<input type="submit" name="submit" value="submit" class="button-big">
</form>
</div>
<% }%>
<% if(!user) {%>
<div class="hint-message"> 你要先<a href="/login" class="link">登陆</a>才能评论,或者<a href="/reg" class="link">注册</a>一个账号
</div>
<% }%>
大家可以看到, 我们看到, 我们还对发布评论的权限做了限制, 只有登陆的用户才可以发布评论. 好啦, 到了见证奇迹的时候了.如果一切没错的话, 运行app, 打开浏览器. 应该是这个样子滴.
但是…..我试着评论了几个之后, 就感觉到有一丝丝奇怪…不能@! 这虽然不是一个那么让人不能接受的事情, 起码是能用的. 但是我还是试着实现了这个功能..
好, 我们在article.ejs添加一个回复的选项
<div class="commentTime">
<span class="comment-post-time"><%= comment.commentTime%></span>
<span class="reply link" data-user-name="<%= comment.userName%>" data-comment-id="<%= index%>">reply</span>
</div>
然后写一段js, js不难, 相信大家能看懂.
<script type="text/javascript">
var replyButton = document.getElementsByClassName('reply'),
textArea = document.getElementsByClassName('textArea')[0],
formWrapper = document.getElementsByClassName('form-wrapper')[0];
for (var i = 0; i < replyButton.length; i++) {
replyButton[i].onclick = function(e) {
var replyUserName = this.getAttribute('data-user-name'),
commentId = parseInt(this.getAttribute('data-comment-id')) + 1,
replyTo = document.createElement('input'),
replyUserNameInput = document.createElement('input');
replyUserNameInput.type = "hidden";
replyUserNameInput.name = "replyUserName";
replyUserNameInput.value = "#" + commentId + "@" + replyUserName + "\n";
replyTo.setAttribute('disabled', "disabled");
replyTo.className = "replyTo";
replyTo.value = "#" + commentId + "@" + replyUserName + "\n";
formWrapper.insertBefore(replyTo, textArea);
formWrapper.insertBefore(replyUserNameInput, replyTo);
textArea.focus();
}
}
textArea.onfocus = function(e) {
formWrapper.style.cssText = "border-color: #3d8fbd";
}
textArea.onblur = function(e) {
formWrapper.style.cssText = "border-color: #dedede";
}
</script>
然后我们再一次运行app. 切换一个用户, 然后…嘻嘻嘻.你就可以这样了.
是不是有点@的意思了. 这样, 我们就实现了评论的功能. 今天的代码在分支day05 github. css文件我没有给出, 大家可以随意发挥, 如果觉得我写的还看得过去, 欢迎copy.
(今天的逼就装到这里, 谢谢大家)