上一节已经实现了登录、注册、发表文章和文章读取的功能,今天咱加上评论、文章页面和作者页面。

评论只能在进入文章页面后才能进行,所以咱们先写文章页面。

在上一节的代码中,我已经给文章标题添加了超链接了,

<a href="/<%= post.user %>/<%= post.time.day%>/<%= post.title %>"><%= post.title %></a>

根据这个链接地址,进入文章页面的路由控制就可以写成这样:

app.get('/:user/:time/:title', function(req,res){
User.get(req.params.user,function(err, user){
Post.getOne(req.params.user, req.params.time, req.params.title, function(err, post){//还记得post.js里面获取文章的函数吧?
if(err){
req.flash('err',err);
return res.redirect('/');
}
res.render('article',{
title: req.params.title,
post: post,
user: req.session.user,
success: req.flash('success').toString(),
error: req.flash('error').toString()
});
});
});
});

接下来写文章页面的视图 article.ejs

<%- include header %>
<p><h2><a href="/<%= locals.post.user %>/<%= locals.post.time.day %>/<%= locals.post.title %>"><%= locals.post.title %></a></h2></p>
<p class="info">
作者:<a href="/<%= locals.post.user %>"><%= locals.post.user %></a> |
日期:<%= locals.post.time.minute %>
</p>
<p><%- locals.post.post %></p>
<p class="info">阅读:<%= locals.post.pv %> | 评论:<%= locals.post.comments.length %>
<%- include footer %>

进入主页点击文章标题看看效果吧?

发现问题了吧?样式都没有了,原因先不说,说完解决方法之后你就明白了:

把header.ejs中引入style.css的路径写成这样:

<link rel="stylesheet" href="/stylesheets/style.css">

好了,ok了!

现在在文章页面后面加上评论,完整的article.ejs为:

<%- include header %>
<p><h2><a href="/<%= locals.post.user %>/<%= locals.post.time.day %>/<%= locals.post.title %>"><%= locals.post.title %></a></h2></p>
<p class="info">
作者:<a href="/<%= locals.post.user %>"><%= locals.post.user %></a> |
日期:<%= locals.post.time.minute %>
</p>
<p><%- locals.post.post %></p>
<p class="info">阅读:<%= locals.post.pv %> | 评论:<%= locals.post.comments.length %> <br /><br />
<% if(locals.post.comments){ %>
<% locals.post.comments.forEach(function(comment, index){ %>
<p><a href="/<%= comment.website %>"><%= comment.name %></a>
<time>回复于 <%= comment.time %></time></p>
<p><%- comment.content %></p>
<% }) %>
<% } %> <form method="post">
<% if(!locals.user){ %>
姓名:<input type="text" name="name" /><br />
邮箱:<input type="text" name="email" /><br />
网址:<input type="text" name="website" /><br />
<% } %>
留言:<br /><textarea name="content" rows="5" cols="80"></textarea>
<br /><input type="submit" value="留言" />
</form>
<%- include footer %>

评论视图有了,下面就是处理过程了,在app.get("/:user/:time/:title",function(){})后面添加:

app.post('/:user/:time/:title', function(req,res){
var comment = null,
date = new Date(),
time = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes();
if(req.session.user){
var name=req.session.user.name;
comment = {"name":name, "email":name+"@gmail.com", "website":"www."+name+".com", "time":time, "content":req.body.content}
} else {
comment = {"name":req.body.name, "email":req.body.email, "website":req.body.website, "time":time, "content":req.body.content}
}
var oneComment = new Comment(req.params.user, req.params.time, req.params.title, comment);
oneComment.save(function(err){
if(err){
req.flash('error', err);
return res.redirect('/');
}
req.flash('success', '评论成功!');
res.redirect('back');//这句话的作用是评论成功后返回到被评论文章
});
});

作者页面和文章页面是类似的,点击作者名字,显示该作者的所有文章。

作者页面路由控制:

app.get('/:user', function(req,res){
User.get(req.params.user, function(err, user){
if(!user){
return res.redirect('/');
} Post.getAll(req.params.user, function(err, posts){
if(err){
req.flash('err',err);
return res.redirect('/');
}
res.render('user',{
title: req.params.user,
posts: posts,
user: req.session.user,
success: req.flash('success').toString(),
error: req.flash('error').toString()
});
});
});
});

作者页面视图user.ejs:

<%- include header %>
<% locals.posts.forEach(function(post, index){ %>
<p><h2><a href="/<%=post.user %>/<%=post.time.day %>/<%=post.title %>"><%= post.title %></a></h2>
<p class="info">
作者:<a href="/<%= post.user %>"><%= post.user %></a> |
日期:<%= post.time.minute %>
</p>
<p><%- post.post %></p>
<p class="info">阅读:<%= post.pv %> | 评论:<%= post.comments.length %></p>
<% }) %>
<%- include footer %>

到目前为止,博客系统已经完成了。还有个地方可以完善一下。现在没有做权限控制,不管登录还是未登录都可以访问页面。稍稍修改一下,未登录用户不可以进入文章页面和作者页面、不可以评论、不可以发布文章、不可以退出,当用户试图执行以上操作的时候,均跳转到登录页面。

咱们在index.js中写一个函数检验用户是否登录:

function checkLogin(req, res, next){
if(!req.session.user){
req.flash('error','请登录');
return res.redirect('/login');
}
next();
}

然后在上面提到的几个路由控制前面加上checkLogin,如在app.get("/logout",function(){});之前加上:app.get('/logout',checkLogin);

对于登录操作,应该只对未登录用户开放,所以添加一个函数校验是否未登录:

function checkNotLogin(req,res,next){
if(req.session.user){
req.flash('error','已登录');
return res.redirect('/');
}
next();
}

然后在login对应的get和post处理前分别添加app.get('/login',checkNotLogin); 和app.post('/login',checkNotLogin);

好了,到现在为止,粗糙的博客系统算是做好了,像csdn的标签功能其实和文章页面差不多,就不写了。

有几个问题做一下小说明,也是我自己在第一次开发的过程中遇到的:

1、路由控制问题。要保证彼此的路由不会相互干扰,比如说,logout不会被作者页面的路由拦截,路由的书写顺序就很重要了。你可以试试把logou路由控制t放在user之后。所以在涉及到正则表达式类型的路由控制的时候,请认真思考路由的书写顺序,当你的路由解析出乎意料的时候,记得调整路由顺序。

2、前面已经说过的样式问题。我第一次开发的时候,参考的是别人给出的解决方案,就是在article.ejs里面在引入一遍style.css,后来总觉得那样不合理,才找出了解决方案。所以引入public下的文件的时候,建议用根目录。

3、我写的这个从一开始到最后,数据结构都没有变过,省了很多。但是真正做开发的时候,不一定会那么顺利。比如我刚开始做的时候,每加一个功能就要修改一次数据结构,然后就会出现先前存进去的数据包含了后面才定义的属性,出现undefined。这时候也不用着急,先清空数据库,基本上就没问题了,还有问题的话,自己看控制台的错误提示,基本上也可以自己解决了。

4、最后,题外话,写程序,思路要尽量清晰一些,开始着手书写代码的时候,要细心,个人觉得写代码可以遵循增量开发的原则,先搭好架子,后期再一步步扩展,一步步测试,这样便于调试。

nodejs--express开发博客系统(三)的更多相关文章

  1. 纯django开发博客系统

    企业级教程:纯django开发博客系统 1.视频教程 https://www.duanshuilu.com/ 2.教程文档 https://www.duanshuilu.com/ 0.课程简介1.简价 ...

  2. 利用Sails.js+MongoDB开发博客系统

    http://yoyoyohamapi.me/categories/利用Sails-js-MongoDB开发博客系统/ 利用Sails.js+MongoDB开发博客系统 Apr 14, 2016 利用 ...

  3. 全栈开发博客系统(nodejs+vuejs+mongodb)

    本篇文章将会介绍如何使用nodejs+vuejs构建个人博客. 主要分三部分内容: 环境准备 博客后端管理系统(admin) 后端服务(主要提供admin及web端接口) 博客前端展示(web) 环境 ...

  4. Node.js开发博客系统

    数据库设计 用户表: id phone password nickname head_img personal_sign level_id create_time update_time is_del ...

  5. ThinkPHP开发博客系统笔记之一

    1.前后台搭建 开发的第一步是搭建前后台系统.搭建前台系统的时候新建了LoginController控制器和登录界面View/Login/index.tpl.模板文件中需要引入js和css文件,这里想 ...

  6. ThinkPHP开发博客系统笔记之二

    1. 登陆验证码 当用户登陆的时候我们希望也弹出验证码,有两种方法可以实现:一是再增加一个弹出验证码的dialog,二是和注册共用一个验证码dialog.第一种方法有大量重复代码,所以我们使用第二种方 ...

  7. Node.js+Express搭建博客系统基本环境安装

    1.下载安装node.js 官网下载地址:https://nodejs.org/en/download/ 2.安装express. 打开node命令行工具,在命令行中输入:npm install -g ...

  8. node.js开发博客系统---前端项目搭建(一)

    Express: https://github.com/petecoop/generator-express 安装node.js和npm 执行: npm install -g yo npm insta ...

  9. React开发博客系统的总结

    React 进入文件APP.js,首先添加react-redux插件,使用react-redux的Provider模块提供管道的储存功能,传入管道的属性必须是store. 然而store参数是一个模块 ...

随机推荐

  1. Windows窗体Winform----show()与showDialog()的区别

    show()与showDialog()的区别 最常见的显示一个新的窗体的方法有两种,下面直接上代码!! A.WinForm中窗体显示 显示窗体可以有以下2种方法:   Form.ShowDialog( ...

  2. Csharp多态的实现(接口)

    1.什么是接口 接口可以看做是一个标准, 所有继承的子类需要按照接口中声明的方法来 接口用关键字 interface 修饰,接口的名字一般是I.........able ,表示我有什么能力 接口一般是 ...

  3. C/C++常用编辑器

    VIM ,www.vim.org/ Emacs, www.gnu.org/software/emacs/ notepad++,www.notepad-plus-plus.org/ Textmate,h ...

  4. mysql innodb init function error

    150414 16:23:07 [ERROR] Plugin 'InnoDB' init function returned error. 150414 16:23:07 [ERROR] Plugin ...

  5. (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解

    PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使用经验,总结一下. 一般对负载均衡的使用是随着网站规模的提升根据不 ...

  6. Android 快速选择联系人

    Activity 代码如下: /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache ...

  7. LaTeX空格

    由于LaTeX 采用的是源文件编译方式,  默认LaTeX会忽略多余的空格, 如果需要产生一个空格,可以使用 命令 \, 注意代表的是空间键. 例如: Jones, et al.\  (1993), ...

  8. this .运算符 和 [] 运算符

    首先看这个  这两个运行结果是不一样的 前两个是3  后面是10 var length = 10; var arr = [function(){console.log(this.length);},2 ...

  9. 为过程或函数sp_Adduser指定了过多的参数

    前些天写用户注册模块,用存储过程添加用户,一开始就报“为过程或函数sp_Adduser指定了过多的参数”.仔细检查数据层的用户添加函数,结果在为存储过程添加sqlparameter参数的时候,数组给写 ...

  10. CVTE 一面

    在网上做完了测评之后,当天就收到面试的通知了,CVTE效率真高.第二天就去参加面试,面试前紧张了一把,后来去到之后发现只有几个应聘者,很多面试官前面都没人,估计现在中午一点,所以都去吃饭了.我和一个同 ...