NodeJs开发个人博客项目预览地址:http://baijiawei.topGitHub地址:https://github.com/bjw1234/blog待安装模块body-parser解析post请求cookies读写cookieexpress搭建服务器markdownMarkdown语法分析生成器mongoose操作Mongodb数据库swig模板分析引擎目录结构db数据库存储目录models数据库模型文件目录public公共文件目录(css,js,img)routers路由文件目录schemas数据库结构文件views模板视图文件目录app.js启动文件package.jsonapp.js文件1.创建应用,监听端口constapp=express();app.get('/',(req,res,next)=>{res.send("HelloWorld!");});app.listen(3000,(req,res,next)=>{console.log("appisrunningatport3000");});2.配置应用模板定义引擎使用的模板app.engine('html',swig.renderFile)参数1:模板引擎的名称,也是模板文件的后缀参数2:表示使用的方法解析处理模板内容设置模板文件存放目录app.set('views','./views')注册模板引擎app.set('viewengine','html')3.使用模板引擎解析文件/***读取views目录下的指定文件并解析返回给客户端*参数1:模板文件*参数2:传递给模板的参数*/res.render('index',{title:'Home',content:'helloswig'});4.开发过程需要取消模板缓存限制swig.setDefaults({cache:false});app.set('viewcache',false);5.设置静态文件托管//当用户访问/pu时blic路径下的文件,则直接返回app.use('/public',express.static(__dirname+'/public'));划分模块前台模块后台模块API模块//根据不同功能划分模块app.use('/',require('./routers/main'));app.use('/admin',require('./routers/admin'));app.use('/api',require('./routers/api'));对于管理员模块admin.jsvarexpress=require('express');varrouter=express.Router();//例如访问/admin/userrouter.get('/user',function(req,res,next){res.send('User');});module.exports=router;前台路由+模板mainmodule/homepage/viewcontentpageapimodule/homepage/register用户注册/登录用户登录/评论评论获取/评论/发表评论提交后台(admin)路由+模板主页/后台主页用户管理/用户用户列表分类管理/分类分类列表/分类/添加分类添加/分类/编辑分类修改/分类/删除分类删除文章内容管理/文章内的内容列表/文章/添加内容添加/文章/编辑内容修改/文章/删除内容删除评论内容管理/commentcommentlist/comment/deletecommentdeletefunctiondevelopmentorder功能模块开发顺序userColumncontentcommentcodingorderthroughSchemadefinitiondesigndatastoragestructurefunctionlogicpagedisplayconnectiondatabase(mongoDB)startMongoDBserver:mongod--dbpath=G:\data\db--port=27017启动服务设置数据库的存储地址和端口varmongoose=require('mongoose');//数据库链接mongoose.connect("mongodb://localhost:27017/blog",(err)=>{if(err){console.log("数据库连接失败");}else{console.log("数据库连接成功");//启动服务器并监听端口app.listen(3000,(req,res,next)=>{console.log("appisrunningatport3000");});}});在schema文件夹中定义数据表结构和用户数据表(users.js)的模型:varmongoose=require('mongoose');module.exports=newmongoose.Schema({//usernameusername:String,//密码password:String});在模型目录下创建user.js模型类varmongoose=require('mongoose');varuserSchema=require('../schemas/users');module.exports=mongoose.model('User',userSchema);处理用户注册前端通过ajaxurl:/api/register后端提交用户名和密码到前端提交(POST)的数据解析varbodyParser=require('body-parser');//bodyParser配置//通过使用这个方法,你可以给req对象添加一个body属性app.use(bodyParser.urlencoded({extended:true}));//在api模块中://1.你可以定义一个中间件统一返回格式varresponseData;router.use(function(req,res,next){//路径默认为'/',访问该目录时调用该中间件responseData={code:0,信息:''};next();});router.post('/register',(req,res,next)=>{console.log(req.body);//判断用户名和密码是否合法//判断是否合法用户名已注册//通过res.json(responseData)向客户端返回json数据//查询数据库User.findOne({//返回一个promise对象username:username}).then(function(userInfo){if(userInfo){//数据库中有这条记录...res.json(responseData);return;}//添加这条信息到数据库varuser=newUser({username:username,password:password});returnuser.save();//返回promise对象}).then(function(newUserInfo){console.log(newUserInfo);res.json(responseData);//数据保存成功});});cookies模块的使用global(app.js)注册使用//设置cookie//只要客户端发出请求,就会通过这个中间件app.use((req,res,next)=>{req.cookies=newcookies(req,res);/***解析用户的cookies信息*查询数据库判断是否为管理员isAdmin*注意:查询数据库是异步操作,next要放在回调中*/req.userInfo={};if(req.cookies.get("userInfo")){尝试{req.userInfo=JSON.parse(req.cookies.get("userInfo"));//查询数据库判断是否为管理员User.findById(req.userInfo._id).then(function(result){req.userInfo.isAdmin=Boolean(result.isAdmin);next();});}catch(e){下一个();}}else{下一步();}});//当用户登录或注册成功后,可以为其设置cookiereq.cookies.set("userInfo",JSON.stringify({_id:result._id,username:result.username}));swig模板引擎1.变量{{name}}2.属性{{student.name}}3.if判断{%ifname==='郭靖'%}你好靖哥{%endif%}4.for循环//arr=[1,2,3]{%forkey,valinarr%}
{{key}}--{{val}}
{%endfor%}5.设置命令用于设置变量并在当前上下文中重用它{%setfoo=[0,1,2,3,4,5]%}{%extends'layout.html'%}//继承一个HTML模板{%include'page.html'%}//include一个模板到当前位置{%blockmain%}xxx{%endblock%}//重写某个block6.autoescape自动编码当你想显示生成的HTML代码后端在某个div中,在模板渲染时会自动编码为字符串形式展示这可以通过以下方式避免:constUser=require('../models/user');//查询所有用户数据User.find().then(function(users){});//根据某个字段查询数据User.findOne({username:username}).then(function(result){});//根据用户ID查询数据User.findById(id).then(function(user){});//根据用户ID删除数据.remove({_id:id}).then(function(){});//修改数据User.update({_id:id},{username:name}).then(function(){});数据分页管理的两个重要方法limit(Number):限制获取的数据项数skip(Number):忽略数据项前的数据项数忽略项数:(当前页-1)*显示的项数在每个页面上//接收传递给pageletquery_page=Number(req.query.page)||1;query_page=Math.max(query_page,1);//最小限制为1query_page=Math.min(Math.ceil(count/limit),query_page);//限制最大计数/限制四舍五入varcur_page=query_page;//当前页面varlimit=10;//每页显示的项目数varskip=(cur_page-1)*limit;//忽略User.find().limit(limit).skip(skip).then(function(users){...//将当前页面page传递给page//将最大页数maxPage传递给page});文章的表结构//forcontent.jsvarmongoose=require('mongoose');varcontentSch=require('../schemas/contentSch');module.exports=mongoose.model('Content',contentSch);//contentSch.jsmodule.exports=newmongoose.Schema({//关联字段-类别类别的id:{//类型type:mongoose.Schema.Types.ObjectId,//引用ref:'Category'},//contenttitletitle:String,//介绍description:{type:String,default:''},//Contentcontent:{type:String,default:''}});//查询文章时关联类别字段Content.find().populate('category').then(contents=>{//然后通过这个方式,我们可以在Content表中找到关联的信息//content.category.category_name});HTML中可以直接使用MarkDown语法高亮