express+mongoose簡易登入,以及封裝思想(純新手向)

rabZhang發表於2019-12-13

專案規劃

  • 前端頁面編寫和ajax請求
  • express接收前端資料,mongoose資料庫連線驗證,登入判斷
  • 對mongoose資料庫連線的封裝

這裡是我上傳的簡單的專案的github地址

github.com/rabZhang/ex…

前端頁面的編寫

  1. 註冊頁面

    這裡就是簡單的編寫了個前端頁面 用到bootstrap官方演示的登入頁面

    express+mongoose簡易登入,以及封裝思想(純新手向)

    <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);
                  }
                }); 
          })
        })
    複製程式碼
  2. 登入頁面

    express+mongoose簡易登入,以及封裝思想(純新手向)
    和註冊頁面幾乎一樣 無非就是改變了下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);
        }
    };
    複製程式碼

    簡單的登入頁面也完成了

  3. 忘記密碼

    express+mongoose簡易登入,以及封裝思想(純新手向)

    這裡忘記密碼就是簡單的模擬密碼修改,從登入頁面新增一個按鈕跳轉到密碼修改頁面,

     url: "http://127.0.0.1:3000/modify" //就修改下ajax請求的url而已其他都一樣
    複製程式碼

    現在前端的基本頁面已經做好了,開始處理後端路由。

後端請求接收以及邏輯處理

  1. 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 沒報錯就可以啦。

  2. 配置路由 先來想想我們需要配置幾個路由

    1. 登入

    在專案資料夾中的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;//匯出自定義模組
     ```
    複製程式碼
    1. 註冊

    在專案資料夾中的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	
    複製程式碼
    1. 修改

    在專案資料夾中的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實現資料庫連線

  1. 安裝mongoosedb模組

    npm install mongodb
    複製程式碼

    建立database檔案模組

    express+mongoose簡易登入,以及封裝思想(純新手向)
    目錄結構分析

  2. 檔案分析

    如果簡單的按照手冊來配置的話可以完全不用這麼麻煩,一個檔案按照手冊從資料庫連線再到文件操作 一系列流程下來最多半小時模組就完成了,但是是要有封裝思想,可能你著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 資料夾
  1. index.js

        const userSchema = require('./userSchema')
        const shopSchema = require('./shopSchema') //引入模組
        
        module.exports = { //一起匯出模組
          userSchema,
          shopSchema
        }
    複製程式碼
  2. userSchema.js

     const mongoose = require('mongoose')
    
     const userSchema=new mongoose.Schema({
      username: String,
      password: String  //這裡就是你建立mongodb 集合的欄位 這裡就可以理解為關係型資料庫裡面的建表環節
     })
     module.exports=userSchema
    複製程式碼
  3. shopSchema.js

    內容同上 自己定義表就好了

model資料夾

這裡的操作很簡單 就是一個簡單的函式

index.js

 const mongoose =require('mongoose');
 const model = ( collectionName, schema ) => {
   return mongoose.model( collectionName, schema ) //兩個引數 一個是建立集合的名稱 ,一個是傳入Schema
   //可以理解為 關係型資料庫中的建立表 然後自定義表名
 }
 
 module.exports = model
複製程式碼
handle資料夾
  1. index.js
```
const shops =require('./shopHandler');
const users =require('./userHandler'); //匯入

module.exports={//匯出
	shops,
	users
}
```
複製程式碼
  1. 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
複製程式碼
  1. 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
複製程式碼

這樣一個簡單的專案就完成了 。

相關文章