从nodejs小白到结合mongoDB,express的移动端小项目制作

分享自己如何从小白了解node,感谢nswbmw大神github上https://github.com/nswbmw/N-blog这一项目让小白可以搭建数据库跑起一个简单项目。直接进入本人学习心得,自己学了大神github项目后大概整理了一个快速学习版,希望能帮助到跟我一样node不知道如何入手的,整个node搭建流程如下

(ps:期间对express的封装突然疑惑了下,疑问express的封装原理等,具体疑问跟解答链接为下,有兴趣可以点击看下https://www.jianshu.com/p/797a4e38fe77,https://cnodejs.org/topic/5396cd60c3ee0b5820f00e2a,https://nodejs.org/dist/latest-v8.x/docs/api/http.html,https://www.cnblogs.com/dabinglian/p/6874290.html)

一、MongoDB安装和启动

1、mongoDB的安装https://www.mongodb.com/download-center#community

从nodejs小白到结合mongoDB,express的移动端小项目制作_第1张图片

2、启动mongoDB(本人安装在了d盘下的MongDB目录,启动前需要在mongodb下新建一个data目录)

从nodejs小白到结合mongoDB,express的移动端小项目制作_第2张图片

window+R启动命令窗口,执行下列命令

从nodejs小白到结合mongoDB,express的移动端小项目制作_第3张图片

二、上面两个步骤启动MongoDB数据库后就是项目搭建,我们搭建一个express框架,接下来的流程均为参考nswbmw大神进行浓缩。

1、新建项目

(1)安装淘宝镜像

$ npm install -g cnpm --registry=https://registry.npm.taobao.org
(2)新建目录e-own,用gitbash直接进入目录,执行

新建好后,手动添加到目录结构如下

从nodejs小白到结合mongoDB,express的移动端小项目制作_第4张图片

  1. models: 存放操作数据库的文件
  2. public: 存放静态文件,如样式、图片等
  3. routes: 存放路由文件
  4. views: 存放模板文件
  5. index.js: 程序主文件
  6. package.json: 存储项目名、描述、作者、依赖等等信息

(3)安装依赖模块

npm i config-lite connect-flash connect-mongo ejs express express-session marked moment mongolass objectid-to-timestamp sha1 winston express-winston --save
npm i https://github.com:utatti/express-formidable.git --save # 从 GitHub 安装 express-formidable 最新版,v1.0.0 有 bug
  1. express: web 框架
  2. express-session: session 中间件
  3. connect-mongo: 将 session 存储于 mongodb,结合 express-session 使用
  4. connect-flash: 页面通知的中间件,基于 session 实现
  5. ejs: 模板
  6. express-formidable: 接收表单及文件上传的中间件
  7. config-lite: 读取配置文件
  8. marked: markdown 解析
  9. moment: 时间格式化
  10. mongolass: mongodb 驱动
  11. objectid-to-timestamp: 根据 ObjectId 生成时间戳
  12. sha1: sha1 加密,用于密码加密
  13. winston: 日志
  14. express-winston: express 的 winston 日志中间件

(4)config/default.js

module.exports = {
  port:3001,
  session:{
    secret:'own',
    key:'own',
    maxAge:2592000000
  },
  mongodb:'mongodb://localhost:27017/own'
}
  1. port: 程序启动要监听的端口号
  2. session: express-session 的配置信息,后面介绍
  3. mongodb: mongodb 的地址,以 mongodb:// 协议开头,myblog 为 db 名

(5)路由(routes/index.js)

module.exports = function(app){
  app.get('/',function(req,res){
    res.send('hello,this is a simple test');
  })
}

(6)项目启动文件index.js(该文件设置了session存储位置,路由,模版引擎)

const path = require('path')
const express = require("express")

const session = require('express-session')
//connect-mongo用于将session持久化到mongodb数据库
const MongoStore = require('connect-mongo')(session)

//flash报错框(flash 中间件应该放到 session 中间件之后加载,因为 flash 是基于 session 实现的。)
const flash = require('connect-flash')

const config = require('config-lite')(__dirname)//读取config下default.js配置项
const routes = require('./routes')
const pkg = require('./package')
const app = express()

//设置模板目录
app.set('views',path.join(__dirname,'views'))
//设置模板引擎为ejs
app.set('view engine','ejs')

//设置静态文件目录
app.use(express.static(path.join(__dirname,'public')))

//session中间件
app.use(session({
  name:config.session.key,//设置cookie中保存session id 的字段名字
  secret:config.session.secret,//通过设置secret来计算hash值并放在cookie中,使产生的signedCookie防篡改
  resave:true,//强制更新
  saveUninitialized:false,//设置为false,强制创建一个session,即使用户未登录
  cookie:{
    maxAge:config.session.maxAge//过期时间,过期后cookie中的sessionid删除
  },
  store:new MongoStore({
    url:config.mongodb
  })
}))
//flash中间件
app.use(flash())
//路由
routes(app)

// 监听端口,启动程序
app.listen(config.port, function () {
  console.log(`${pkg.name} listening on port ${config.port}`)
})

上面几个配置好后,确保已经开启Mongodb的同时在进入e-own目录下下面命令启动项目

在浏览器中输入网址localhost:3001,查看到界面如下,则可继续进行下一步,否则请确保程序正确运行后再继续下面的操作。

三、上面的简单的三步骤只是简单的进行页面跳转,接着我们以实现登录注册为例子,通过连接数据库跟操作数据跟界面的搭建基本的了解整个流程

  1. checkLogin: 当用户信息(req.session.user)不存在,即认为用户没有登录,则跳转到登录页,同时显示 未登录 的通知,用于需要用户登录才能操作的页面
  2. checkNotLogin: 当用户信息(req.session.user)存在,即认为用户已经登录,则跳转到之前的页面,同时显示 已登录的通知,如已登录用户就禁止访问登录、注册页面

(1)路由设置routes/index.js(打开页面后直接进入登录页)

module.exports = function(app){
  app.get('/',function(req,res){
    res.redirect('/signin')
  })
  app.use('/signin',require('./signin'))
}

routes/signin.js

const express = require('express');
const router = express.Router()


//get/signin登录页
router.get('/',checkNotLogin,function(req,res,next){
  res.render('signin')
})

module.exports = router;

signin.js中res.render('signin')用户渲染界面,index.js下通过app.set("views",path.join(__dirname,'views'))。app.set('view engine','ejs')设置了模板引擎为ejs,模板目录,app.use(express.static(path.join(__dirname,'public')))指定了静态文件目录,直接上本人的signin.ejs代码,个人比较想通过nodejs制作一个移动端项目,因此引入rem.js跟reset.css

(views/header.ejs)




  
    
    
    <%= blog.title %>
    
    
    
    
  
  

(views/footer.ejs)


(views/signin.ejs)

<%- include('header') %>

<%- include('footer') %>

public/css/custom.css

/*登录页面样式*/
.login-content{
  /*背景渐变*/
  background:#d4a112;
  background: -webkit-gradient(linear, left top,left bottom, color-stop(0, rgb(231, 194, 194)),
  color-stop(1, #d4a112));
  background: -ms-linear-gradient(right, #F5DA91, #d4a112);
  background: -o-linear-gradient( #F5DA91, #d4a112);
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F5DA91', endColorstr
  ='#d4a112', GradientType=0);
  box-shadow: none;
  text-align:center;
  position: absolute;
  top:0;right:0;bottom:0;left:0;
  padding:0 10%;
}
.logo-content{
  text-align:center;  
  padding:7rem 0;
}
.login-title{
  color:#fff;
  font-size:3rem;
}
.input-content{
  line-height:7rem;
  text-align: center;
}
.input-radius{
  width:100%;
  height:4rem;
  padding:0.3rem;
  font-size:1.5rem;
  margin:0 auto;
  border-radius:10px;
  border:1px solid #fff;
}
.btn-login{
  width:100%;
  height:5rem;
  margin-top:5rem;
  text-align:center;
  font-size:2rem;
  color:#fff;
  border-radius:10px;
  outline:none;
  background-color:#DF7614;
  border:none;
}

public/css/reset.css

@charset 'utf-8';

html{color:#000;background:#FFF;font-family:'Microsoft YaHei',sans-serif,Arial;}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td,strong{padding:0;margin:0;font-family:'Microsoft YaHei',sans-serif,Arial;}
table{border-collapse:collapse;border-spacing:0;}img{border:0;}a{text-decoration:none; color:#000; outline:none;}a:hover{text-decoration:underline;}
var,em,strong{font-style:normal;}
em,strong,th,var{font-style:inherit;font-weight:inherit;}
li{list-style:none;}
caption,th{text-align:left;}
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style: inherit;font-weight:inherit;}

input,button,textarea,select{*font-size:100%;}

.clearfix {*zoom:1}
.clearfix:after {content:'\200B';clear:both;display:block;height:0px}

public/js/rem.js

(function (doc, win) {
  console.log("dpr:" + win.devicePixelRatio);
  var docEle = doc.documentElement,
      isIos = navigator.userAgent.match(/iphone|ipod|ipad/gi),
      dpr = Math.min(win.devicePixelRatio, 3);
  scale = 1 / dpr,

      resizeEvent = 'orientationchange' in window ? 'orientationchange' : 'resize';
  docEle.dataset.dpr = dpr;

  var metaEle = doc.createElement('meta');
  metaEle.name = 'viewport';
  metaEle.content = 'user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale;
  docEle.firstElementChild.appendChild(metaEle);

  var recalCulate = function () {
      var width = docEle.clientWidth;
      if (width / dpr > 640) {
          width = 640 * dpr;
      }
      docEle.style.fontSize = 20 * width / 750 + 'px';

  };

  recalCulate();
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvent, recalCulate, false);
})(document, window);

上面文件确保正确后,确保mongodb开启的同时进入文件目录执行node index即可得到下图登录页

从nodejs小白到结合mongoDB,express的移动端小项目制作_第5张图片

点击登录,需验证账号密码是否已填,填写后需请求数据库是否存在该用户,若存在这进入主页,若不存在则进入注册页面,该逻辑在sigin.js里路由进行处理

routes/signin.js

const sha1 = require('sha1')
const express = require('express')
const router = express.Router()

const UserModel = require('../models/users')
const checkNotLogin = require('../middlewares/check').checkNotLogin

// GET /signin 登录页
router.get('/', checkNotLogin, function (req, res, next) {
  res.render('signin')
})

// POST /signin 用户登录
router.post('/', checkNotLogin, function (req, res, next) {
  const name = req.fields.name
  const password = req.fields.password

  // 校验参数
  try {
    if (!name.length) {
      throw new Error('请填写用户名')
    }
    if (!password.length) {
      throw new Error('请填写密码')
    }
  } catch (e) {
    req.flash('error', e.message)
    return res.redirect('back')
  }

  UserModel.getUserByName(name)
    .then(function (user) {
      if (!user) {
        req.flash('error', '用户不存在')
        return res.redirect('back')
      }
      // 检查密码是否匹配
      if (sha1(password) !== user.password) {
        req.flash('error', '用户名或密码错误')
        return res.redirect('back')
      }
      req.flash('success', '登录成功')
      // 用户信息写入 session
      delete user.password
      req.session.user = user
      // 跳转到主页
      res.redirect('/posts')
    })
    .catch(next)
})

module.exports = router

上面通过mongodb查询数据库,接着便进入数据库的相关操作,lib/mongo.js链接数据库并建立User集合

lib/mongo.js

const config = require('config-lite')(__dirname)
const Mongolass = require("mongolass")
const mongolass = new Mongolass()
const moment = require('moment')
const objectIdToTimestamp = require("objectid-to-timestamp")

//根据id生成创建时间created_at
mongolass.plugin("addCreatedAt",{
  afterFind:function(results){
    results.forEach(function(item){
      item.created_at = moment(objectIdToTimestamp(item._id)).format("YYYY-MM-DD HH:mm")
    })
    return result
  },
  afterFindOne:function(result){
    if(result){
      result.created_at = moment(objectIdToTimestamp(item._id)).format("YYYY-MM-DD HH:mm")
    }
    return result
  }
})
mongolass.connect(config.mongodb)
exports.User = mongolass.model('User', {
    name: { type: 'string', required: true },
    password: { type: 'string', required: true },
    avatar: { type: 'string', required: true },
    gender: { type: 'string', enum: ['m', 'f', 'x'], default: 'x' },
    bio: { type: 'string', required: true }
  })
  exports.User.index({ name: 1 }, { unique: true }).exec()// 根据用户名找到用户,用户名全局唯一

对数据库的创建查询方法在models文件夹下处理

models/users.js


const User = require('../lib/mongo').User

module.exports = {
  // 注册一个用户
  create: function create (user) {
    return User.create(user).exec()
  },

  // 通过用户名获取用户信息
  getUserByName: function getUserByName (name) {
    return User
      .findOne({ name: name })
      .addCreatedAt()
      .exec()
  }
}

至此,我们已经实现了登录后进入主页的流程,其他流程类比一下登录页,创建数据库相关集合在lib/mongo.js,数据库处理逻辑,增删改查均在models文件夹下创建对应的文件进行处理,界面均为views下的ejs文件,且通过res.render引入。

(小插曲)期间踩坑两小时,报如下错误,只因为

 

从nodejs小白到结合mongoDB,express的移动端小项目制作_第6张图片

解决:确保此处正确书写

router.post("/",checkNotLogin,function(req,res,next){
  const name = req.fields.name
  const password = req.fields.password
  console.log("name passwprd",name,password);
})

由于时间关系,可能有些地方不够详细,有错之处请指出。接下来自己将这个移动端项目完善再写该博客后续,再次感谢大神们对知识的分享,让小白有了更多的学习资源来研究新的技术

你可能感兴趣的:(Js,nodejs,express,mongodb,nodejs,mongoDB,express,移动端)