项目规划
- 前端页面编写和ajax请求
- express接收前端数据,mongoose数据库连接验证,登录判断
- 对mongoose数据库连接的封装
这里是我上传的简单的项目的github地址
前端页面的编写
-
注册页面
这里就是简单的编写了个前端页面 用到bootstrap官方演示的登录页面

<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>直接引用的bootCDN然后简单的传了个ajax
$(function(){ $('.btn').on('click',function(){ let username=$('#username').val(); let password=$('#password').val(); $.ajax({ type: "POST", url: "http://127.0.0.1:3000/register", dataType:'json', data:{ username, password }, success: function(response) { const result = JSON.parse( response) switch ( result.status ) { case 1: // 注册成功 if ( confirm('恭喜您注册成功,是否要跳转到登录页面') ){ setTimeout( function () { location.href = "./login.html" },2000) } break; case 2: // 用户名重复了 alert('用户名已经重复,请您确认后在注册') break; } }, error: function(response) { console.log(response); } }); }) }) -
登录页面
和注册页面几乎一样 无非就是改变了下url的地址
url: "http://127.0.0.1:3000/login",然后再加入了登录的token的判断
const token=cookieUtil.get('token');//这里的cookieUtil是下面封装的 if(token){ alert('检测到已经登录,两秒后转到首页'); setTimeout(function(){ location.href="./index.html"; },2000) }期间用到了自己封装的cookie.js用来获取和设置cookie
const cookieUtil={ get: function(key) { if (document.cookie) { //判断是否有cookie let arr = document.cookie.split('; '); //拆分cookie for (let i = 0; i < arr.length; i++) { let item = arr[i].split('='); //拆分cookie,获得key和value // 遍历寻找key 返回值 if (item[0] === key) return item[1]; } return ''; //如果遍历结束 都没有找到 返回空字符串 } }, set: function(key, value, day) { if (day) { var d = new Date(); d.setDate(d.getDate() + day); document.cookie = `${key}=${value};expires=${d};path=/`; } else { document.cookie = `${key}=${value};path=/`; } }, remove: function(key) { this.set(key, '', -1); } };简单的登录页面也完成了
-
忘记密码

这里忘记密码就是简单的模拟密码修改,从登录页面添加一个按钮跳转到密码修改页面,
url: "http://127.0.0.1:3000/modify" //就修改下ajax请求的url而已其他都一样现在前端的基本页面已经做好了,开始处理后端路由。
后端请求接收以及逻辑处理
-
node.js/express基础包配置
我这里是直接用express-generator 需要的小伙伴可以全局安装
npm install express-generator -g npm install //安装express中的json包依赖然后直接在项目文件下打开bash输入
express install '项目名' -e -S (这里的e指的是express ejs模板引擎的支持,不选的话默认jade)express安装完之后进入文件夹 没有全局安装的nodemon的小伙伴可以全局安装下nodemon 热更新,不想全局安装的可以安装在包依赖里面
npm install nodemon //装完了包依赖会显示这样,当然全局安装的就不需要执行这一步了 "dependencies": { "nodemon": "^2.0.1" }打开package.json,找到start 修改成下面这样
"scripts": { "start": "nodemon ./bin/www" },然后试运行npm start 没报错就可以啦。
-
配置路由 先来想想我们需要配置几个路由
- 登录
在项目文件夹中的routes路由文件夹下面创建login.js文件
``` const express=require('express'); //引入第三方模块 const router=express.Router(); //配置路由 const jwt=require('jsonwebtoken'); //登录用的token const path=require('path'); //文件路径 内置模块 const fs=require('fs');//文件操作 内置模块 const {users}=require('../database'); //后面会讲到的 自定义模块 数据库封装 router.route('/login') //如果这里写了路由,那么app.js路由组中就不必写路由了 .post(async (req,res,next)=>{ //三个参数 请求 相应 路由中间件的next (async)设置es6中的generator异步操作 let results=req.body; if(!results.token){ //如果登录没有传token const private_key=fs.readFileSync(path.join(__dirname,'..','rsa/private_key.pem')) //私钥 //如果不会配置私钥的朋友可以去查看下npm 中jsonwebtoken手册中 这边配置比较麻烦 另开一贴介绍 const token =jwt.sign({username:results.username}, private_key, { algorithm: 'RS256'})//token创建 const searchitem = await users.query(results); //(await)es6中的generator异步操作 yield res.json( //返回searchitme中的返回值 JSON.stringify({ status:searchitem.status, msg:searchitem.msg, token:searchitem.status==1 && token || '用户名密码错误,token不返回' })) } }) module.exports=router;//导出自定义模块 ```- 注册
在项目文件夹中的routes路由文件夹下面创建register.js文件
const express=require('express'); //引入第三方模块 const router=express.Router();//路由 const {users}=require('../database')//自定义数据库连接 router.route('/register') //register路由 .post(async (req,res,next)=>{ //与登录同理 const results=await users.add(req.body); res.json( JSON.stringify({ status:results.status, info:results.info }) ) }) module.exports=router- 修改
在项目文件夹中的routes路由文件夹下面创建modify.js文件
const express =require('express') const router =express.Router(); const {users} =require('../database');//这里是引入数据库连接自定义模块 后面会讲 router.route('/modify') .post(async (req,res,next)=>{ const data =req.body; const results=await users.update(data); res.json(JSON.stringify({ status:results.status, msg:results.msg })) }) module.exports=router这样三个子路由就创建好了 接下来去app.js中引入子路由和配置中间件路由组
var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); var loginRouter = require('./routes/login'); var registerRouter=require('./routes/register'); var modifyRouter=require('./routes/modify'); var cors = require('cors'); //这里提前引入cors的包 等下要解决跨域问题 cors npm直接下 var app = express();配置路由中间件
app.use(cors({ //这里实现跨域 不太懂的可以去https://www.npmjs.com/ 看下cors手册 "origin": "*", "methods": "GET,HEAD,PUT,PATCH,POST,DELETE", "preflightContinue": false, "optionsSuccessStatus": 200 })) app.use('/', indexRouter); //这里都是中间件的路由组 '/'是路由组 如果子路由配置完 这里就不用再配置了 app.use('/users', usersRouter); app.use('/',loginRouter); app.use('/',registerRouter); app.use('/',modifyRouter);这样配置完后 已经可以从前端发送数据请求然后后端接收了。只不过少了数据库连接模块。 这里我们使用的是mongoose模块来完成,同样你也可以在npmjs.com中查看手册
mongoose实现数据库连接
-
安装mongoosedb模块
npm install mongodb创建database文件模块
目录结构分析
-
文件分析
如果简单的按照手册来配置的话可以完全不用这么麻烦,一个文件按照手册从数据库连接再到文档操作 一系列流程下来最多半小时模块就完成了,但是是要有封装思想,可能你着30分钟写完之后你以后再回 来看,或者在对数据维护,其实非常不方便,这时候就需要引入封装思想
index.js 这是database的入口文件
//引入mongoose const mongoose = require('mongoose') //引入模块 //连接数据库 const connect=require('./connect');//数据库连接封装 connect(); // 创建骨架 const {users,shops}=require('./handle')//模型操作 module.exports = { //导出 users,shops }constant.js这里是方便线上修改的模块 ,把以后容易修改的变量值都放入这里
const HOST='127.0.0.1' //本地服务器域名 //const HOST ='www.baidu.com' //以后项目上线需要的定位地址方便修改 const DB_NAME=1910 //数据库名 const DB_URL=`mongodb://${ HOST }:27017/${ DB_NAME }`; module.exports={ DB_URL }connect.js数据库连接操作模块
const mongoose = require('mongoose'); const {DB_URL}=require('./constant.js') function connect(){ mongoose.connect(DB_URL,{ useNewUrlParser: true, useUnifiedTopology: true },err=>{ if(err){ console.log(err) }else{ console.log('数据库连接成功'); } }) } module.exports=connect
schema 文件夹
-
index.js
const userSchema = require('./userSchema') const shopSchema = require('./shopSchema') //引入模块 module.exports = { //一起导出模块 userSchema, shopSchema } -
userSchema.js
const mongoose = require('mongoose') const userSchema=new mongoose.Schema({ username: String, password: String //这里就是你创建mongodb 集合的字段 这里就可以理解为关系型数据库里面的建表环节 }) module.exports=userSchema -
shopSchema.js
内容同上 自己定义表就好了
model文件夹
这里的操作很简单 就是一个简单的函数
index.js
const mongoose =require('mongoose');
const model = ( collectionName, schema ) => {
return mongoose.model( collectionName, schema ) //两个参数 一个是创建集合的名称 ,一个是传入Schema
//可以理解为 关系型数据库中的创建表 然后自定义表名
}
module.exports = model
handle文件夹
- index.js
```
const shops =require('./shopHandler');
const users =require('./userHandler'); //导入
module.exports={//导出
shops,
users
}
```
- shopHandler.js
const {shopSchema}=require('../schema');
const model=require('../model')
const shopModel=model('shops',shopSchema)//使用model文件夹下的函数 实现表创建
const shops = { //增删查改
add () {},
del () {},
update () {},
query () {}
}
module.exports = shops
- userHandler.js
const {userSchema}=require('../schema');
const model=require('../model')
const userModel=model('users',userSchema)
const users = {
add (data) {
return new Promise((resolved,rejected)=>{ //和之前路由子文件 下面对应 Promise操作修改异步操作 实现同步
userModel.find({},(err,docs)=>{
const f=docs.some(item=>data.username==item.username) //如果传来的注册账户和数据库中的有相同的
if(f){
resolved({
status:2,
info:'用户名重复'
})
}else{
const userEnity=new userModel(data)
userEnity.save(err=>{
if(err){
rejected({
status:0,
info:'注册失败'
})
}else{
resolved({ //返回给子路由文件,再由子路由文件传给前端
status:1,
info:'注册成功'
})
}
})
}
})
})
},
del () {},
update(data) {
return new Promise((resolved,rejected)=>{
userModel.find({username:data.username,password:data.password},(err,docs)=>{//mongodb语法
//查找账户名和密码相同的文档
if(docs.length!=0){
userModel.findById(docs[0]._id,(err,doc)=>{
doc.password=data.newpassword;
doc.save(err=>{
if(err){
rejected({
status:0,
msg:'修改失败'
})
}else{
resolved({
status:1,
msg:'修改成功'
})
}
})
})
}else{
resolved({
status:2,
msg:'账号或密码不正确,无法修改'
})
}
})
})
},
query (data) {
return new Promise((resolved,rejected)=>{
userModel.find({},(err,docs)=>{
const f=docs.some(item=>(item.username==data.username&&item.password==data.password))
if(f){
resolved({
status:1,
msg:"登录成功"
})
}else{
rejected({
status:2,
msg:"登陆失败,用户名或是密码不正确"
})
}
})
}).catch((err)=>{
return err;
})
}
}
module.exports = users
这样一个简单的项目就完成了 。