node项目实例
博客项目简介:基于Node.js+Express+Mongodb+Mongoose开发
一、创建文件夹:
项目目录:my_blog
app.js入口文件
views:视图模板
static:存放静态资源
controller:控制路由
models:使用db的模板
libs:后端使用
uploads:接收上传的图片文件夹
二、下载模板
http://www.cssmoban.com/cssthemes/8138.shtml
三、下载第三方包
- 根据项目需求,下载所需的第三方包;
express、mongoose、ejs、formidable(表单)、uuid(图名)
四、设计路由
- 根据需求设计路由,并将html模板中相同的部分使用ejs模板引入;
(可以先设计登录页面,之后判断是否登录,才能发表文章)
六、添加数据库
- 连接:
(1)在libs文件夹创建一个专门连接的js文件
(2)里面只引入mongoose和连接,
(3)之后在app.js头部引入;
require('./libs/connectdb.js')
- 创建db
(1)在models创建一个文章db;
(2)定义Schema约束
(3)定义一个添加文章的函数,两个形参(传入的值,回调函数);
(4)如果添加出错return callback(err),如果成功return callback(null);
// 添加时间:
addtime:{
type:Date,
default:Date.now
}
function addArticle(data,callback){
models.create(data,(err)=>{
if(err){ //添加成功
return callback(err);
}else{ //添加失败 返回null方便判断
return callback(null);
}
})
}
- 处理数据
(1)处理拿到的数据,引入数据文件;
(2)在添加文章路由文件引入设计的db模块;
(3)将图片的路径添加到fields对象中,再添加一个用户id,获取哪个用户上传的;
(4)将fields对象作为实参调用添加文章的函数
(5)处理添加成功或者失败;
(5)使用ejs模板往前台传入数据;
fields.uname = uname; //设计一个用户名,方便后期渲染
fields.pic = picName; //往fields里面添加属性;
articleDB.addArticle(fields,result=>{
if(result){ //处理添加失败
res.render('msg.html',{curtitle:'上传失败',curUrl:'/user/publish'})
}else{ //处理添加成功
res.render('msg.html',{curtitle:'上传成功',curUrl:'/user/publish'})
}
})
数据库结构:创建models文件
const mongoose = require('mongoose');
//约束规则
let Schemas = new mongoose.Schema({
uname:String,
title:String,
desc:String,
contents:String,
pic:String,
del:{
type:Number,
default:1 //1为显示 0为删除;
},
addtime:{
type:Date,
default:Date.now
}
})
//定义模型
let models = mongoose.model('article',Schemas);
//定义添加文章
function addArticle(data,callback){
models.create(data,(err)=>{
if(err){ //添加成功
return callback(err);
}else{ //添加失败
return callback(null);
}
})
}
//定义查询文章并渲染
function findArticle(conditions,projection,options,callback){
models.find(conditions,projection,options,(err,docs)=>{
if(err){ //查询失败;
return callback(err,[])
}else{ //查询成功
return callback(null,docs);
}
})
}
//查询条数
function findCount(data,callback){
models.countDocuments(data,(err,cond)=>{
if(err){ //查询失败
return callback(err,0);
}else{
return callback(null,cond);
}
})
}
function updateArticle(id,update,ccc,callback){
models.findByIdAndUpdate(id,update,ccc,err=>{
if(err){
return callback(err);
}else{
return callback(null);
}
})
}
//将文章暴露出去;
module.exports = {addArticle,findArticle,findCount,updateArticle}
路由结构:创建ArticleRouter.js,之后在app.js引入
const express = require('express')
let router = express.Router();
const Articledb = require('../models/Articledb.js');
//博客首页
router.get('/',(req,res)=>{
Articledb.findArticle({del:1},{},{limit:9,sort:{addtime:-1}},(err,docs)=>{
if(err){ //查询失败
return res.send('Not Found:'+err);
} //查询成功..
res.render('index-index.html',{docs})
})
})
//博客列表页
router.get('/lists/:pid',(req,res)=>{
//定义每页显示的条数
let limits = 2;
//定义每页跳过多少条
let skips = (req.params.pid-1)*limits;
//查询条数
let pagenum = 0;
Articledb.findCount({del:1},(err,total)=>{
//定义总共的页数
pagenum = Math.ceil(total/limits);
})
//渲染列表
Articledb.findArticle({del:1},{},{limit:limits,skip:skips,sort:{addtime:-1}},(err,docs)=>{
if(err){ //查询失败
return res.send('Not Found:'+err);
} //查询成功..
res.render('index-blog.html',{docs,pagenum});
})
})
//博客详情
router.get('/detail',(req,res)=>{
res.render('index-blog-detail.html');
})
//联系我们
router.get('/contact',(req,res)=>{
res.render('index-contact.html');
})
//关于我们
router.get('/about',(req,res)=>{
res.render('index-about.html');
})
module.exports = router;
app引入ArticleRouter.js
let articleRouter = require('./ArticleRouter.js')
app.use('/blog', articleRouter) // articleRouter的每个路由都得添加一个blog
七、渲染页面
(1)定义查询数据库
function findArticle(conditions,projection,options,callback){
models.find(conditions,projection,options,(err,docs)=>{
if(err){ //查询失败;
return callback(err,[])
}else{ //查询成功
return callback(null,docs);
}
})
}
(2)渲染到页面
Articledb.findArticle({del:1},{},{limit:9,sort:{addtime:-1}},(err,docs)=>{
if(err){ //查询失败
return res.send('Not Found:'+err);
} //查询成功..
res.render('index-index.html',{docs})
})
通过ejs模板引擎来循环,将数据发送过去;
八、设计列表页
- 计算出数据库总的页数,之后设计path路径或查询字符串;
使用model.countDcuments(data,callback);
- 通过limit和skip定义每页显示的条数,并计算出总的页数;
方法:(页数-1)*条数;
- 在前端页面通过for循环渲染页数;
九、登录页面
- 将输入的用户名调用到后台数据库查询,判断传入的数据的长度是否为0;
- 当账号正确之后验证密码是否正确,正确之后开始设置session;
- 渲染页面msg提示信息页面;
十、用户首页
- 判断sessionid是否存在,如果不存在,则跳转到提示页面,让用户登录;
- 利用session获取当前的用户,并使用查询数据库;
- 将当前用户发表的文章渲染到当前用户的首页;
技巧:渲染页面时可以做一个表格,给每一行添加一个修改和删除的按钮;
十一、修改文章
- 点击修改用path路径给后台传入一个_id,后台利用_id查询数据;
- 设计两个路由和添加修改文章的页面;
- 将获取到的_id的数据渲染到页面(先显示,后修改),并添加一个隐藏域_id,添加一个图片显示的标签;
- 将发表文章的js内容复制到修改文章,将创建文章改成findByIdAndUpdate();
- 修改失败回到修改页面,需要将id传到path路径;
十二、删除文章
- 设计一个调用ajax的函数,将点击的_id传到后台;
- 在后台将收到的_id的值改为逻辑删除;
十三、文章详情页面
- 点击之后将_id通过ajax传到后台,将内容显示出来;