Node.js 配合 express 框架、ejs 、mongodb 實現應用 && [使用 TypeScript 重構]

1、Node.js默認使用commonJs的模塊化方案,TypeScript默認是ES6的模塊化方案,二者有本質區別。

  • 1.Node.js的去尋找引入的依賴時,若是是Node自帶的模塊,好比fs文件模塊,只須要填寫fs便可。若是是本身定義的模塊,那麼須要加入./(使用相對路徑),暴露接口使用exports或者module.exportscss

  • 2.TypeScript的import * from url 的引入依賴,須要填寫完整的相對路徑,不然是找不到模塊的,暴露接口使用export .html

  • 3.Node中使用TypeScript須要下一些包去支持,好比express框架這些,還有一些支持內置對象的包:node

  • 4.github源碼下載地址jquery

"dependencies": {
    "@babel/core": "^7.4.0",
    "@types/core-js": "^2.5.0",
    "browserify": "^16.2.3",
    "connect-mongo": "^2.0.3",
    "cookie-parser": "^1.4.4",  
    "ejs": "^2.6.1",
    "express": "^4.16.4",
    "express-session": "^1.15.6",
    "mongoose": "^5.4.19",
    "nodemon": "^1.18.10",
    "sha1": "^1.1.1"
  },
  "devDependencies": {
    "@types/express": "^4.16.1",
    "@types/node": "^11.11.4",
    "ts-loader": "^5.3.3",
    "ts-node-dev": "^1.0.0-pre.32",
    "typescript": "^3.3.4000",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0"
  }

 '具體還須要什麼,能夠上網去搜索下'

複製代碼

2、入口文件,咱們使用 ejs 引擎渲染(res.render() )

  • 1.Node.js使用ejs渲染的核心技巧是渲染數據的指定webpack

  • 2.儘可能一個渲染數據對象包括全部的渲染內容git

  • 3.一個渲染對象能夠有不少個屬性,每次get請求github

時先發送一個空的對象到後端,再根據需求邏輯指定web

對象屬性和內容,最後仍是傳輸那個對象回來。避免了ajax

傳送過多的對象,代碼看起來很複雜mongodb

  • 4.渲染數據的位置在渲染的ejs文件中的放置, 若是須要樣式,能夠事先在HTML結構中包一層HTML結構, 而後用CSS定義好。
'這是Node.js版本'
 
 '//入口文件使用了兩個路由器路由,分別處理get和post請求邏輯。 即便是同一個路由,可是請求方式不同,他們的處理邏輯不會衝突'
const express = require('express');
const db = require('./common/db');
const app = express();
const uirouter = require('./router/uirouter');
const postrouter = require('./router/postrouter');
app.set('views', 'views');
app.set('view engine', 'ejs');

db.then(() => {
    app.use(uirouter);
    app.use(postrouter);
})

app.listen(8080, err => {
    if (!err) {
        console.log('端口號監聽成功')
    } else {
        console.log('端口監聽失敗', err)
    }
})


-----------------

'這是TypeScript版本'

import express from './node_modules/@types/express/index';
import db from './common/db1';
import uirouter from './router/uirouter1';
import postrouter from './router/postrouter1';
const app: any = express();
app.set('views', 'views');
app.set('view engine', 'ejs');
db.then((): void => {
    app.use(uirouter);
    app.use(postrouter);
});
app.listen(8080, (err): void => {
    if (!err) {
        console.log('服務器鏈接成功');
    } else {
        console.log('服務器鏈接成功');
    };
});

複製代碼

3、get請求的路由處理模塊

  • 1.路由模塊的核心,一個路由處理一個邏輯

  • 2.res.end / send / render後面再寫邏輯也不會執行了,由於已經返回響應。

  • 3.對於cookie的使用咱們須要依賴第三方中間件

  • 4.res.render()裏面是寫ejs渲染的文件,因此能夠不用寫ejs的後綴

  • 5.res.redirect()裏面寫的是定向的那個路由,指定前往那個路由,

而後根據那個路由的邏輯處理,此時瀏覽器中的url會改變。這就叫重定向

'//這裏咱們使用了第三方中間件處理cookie而且 攜帶數據,大概設計思路: 1.沒有登陸過不能進入我的中心,會跳轉到登陸界面 2.登陸事後會有一個免登陸期限進入我的中心 3.在登陸界面能夠經過用戶名和郵箱找回密碼 4.在 Node 端處理邏輯,只有res.redirect()能夠 改變瀏覽器的網址,切記。 5.每一個路由器路由表明每一個不一樣的邏輯 6.get模塊只處理渲染哪一個頁面的邏輯'
const { Router } = require('express');
const model = require('../common/model');
const cookieParse = require('cookie-parser');
const router = new Router();
router.use(cookieParse())
router.get('/index', (req, res) => {
    res.render('index.ejs', { err: "" })
})
router.get('/', (req, res) => {
    res.redirect('/index');
});
router.get('/login', (req, res) => {
    res.render('login.ejs', { err: "" });
});
router.get('/register', (req, res) => {
    res.render('register.ejs', { err: "" });
});
router.get('/reset', (req, res) => {
    res.render('reset.ejs', { err: '' });
});
router.get('/usercenter', async (req, res) => {
    const result = await model.findOne({ _id: req.cookies.userid });
    if (!result) {
        res.redirect('/login')
        return
    }
    res.render('usercenter.ejs', { err: "" });
});
module.exports = router;



複製代碼

4、post模塊,處理各類數據庫的CRUD操做,後臺邏輯。(核心)

  • 1.CRUD操做所有依賴模型對象來執行。
  • 2.限制對象一旦生成那麼沒法改變,除非刪除數據庫
  • 3.限制對象的增刪改查都返回的是一個promise對象,

若是這時候去 if()裏判斷,不管有什麼樣的結果,都是true,

並且這個CRUD 操做都是異步,因此咱們把外部函數變成 async 函數,

這樣能夠配合await 實現最佳異步,還能夠獲取他們的返回值進行

if判斷。(Node.js的後端核心)

const { Router } = require('express');
const express = require('express');
const model = require('../common/model');
const cookieParse = require('cookie-parser');
const sha1 = require('sha1');
const router = new Router();
router.use(cookieParse())
router.use(express.urlencoded({ extended: true }))
router.post('/login', async (req, res) => {
    const { username, password } = req.body;
    const result = await model.findOne({ username, password: sha1(password) });
    if (!result) {
        res.render('login', { err: { usernameloginerr: '用戶名或密碼錯', username: username } })
        return;
    }
    const userid = result.id;
    res.cookie('userid', userid, {maxAge:1000*60*10});
    res.redirect('/usercenter')
    return
});
router.post('/register', async (req, res) => {
    const { username, password, repassword, email } = req.body;
    const err = {};
    const usernameReg = /^[A-Za-z0-9_]{5,10}$/;
    const passwordReg = /^[A-Za-z0-9_]{5,12}$/;
    const emailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
    if (!usernameReg.test(username)) {
        err.usernamereerr = '用戶名格式錯誤';
    }
    if (!passwordReg.test(password)) {
        err.passworderr = '密碼格式錯誤';
    }
    if (repassword !== password) {
        err.repassworderr = '兩次密碼輸入不一致';
    }
    if (!emailReg.test(email)) {
        err.emailerr = '郵箱格式錯誤';
    }
    const usernameresult = await model.findOne({ username });
    if (usernameresult) {
        err.usernamereerr = '用戶名已存在';
        res.render('register', { err })
        return
    };
    const emailresult = await model.findOne({ email });
    if (emailresult) {
        err.emailerr = '郵箱已被註冊';
        res.render('register', { err })
        return
    }
    if (err.usernamereerr || err.passworderr || err.repassworderr || err.emailerr) {
        err.username = username;
        err.email = email;
        res.render('register', { err })
        return
    }
    model.create({
        username: username,
        password: sha1(password),
        email: email
    })
    res.redirect('/index')
});
router.post('/reset', async (req, res) => {
    const { username, password, repassword, email } = req.body;
    const err = {};
    const result = await model.findOne({ username, email });
    if (!result) {
        if (repassword !== password) {
            err.repassworderr = '兩次密碼輸入不一致'
        }
        err.usernamereerr = '用戶名或者郵箱輸入有誤';
        err.emailerr = '用戶名或者郵箱輸入有誤';
        res.render('reset.ejs', { err }) 
        return
    } else {
        await model.updateOne({ username, email }, { password: sha1(password) });
        res.redirect('/usercenter');
        return
    }

})
module.exports = router;

複製代碼

5、工具類模塊 model對象和database模塊 有天坑 須要注意

限制對象一旦生成那麼沒法改變,除非刪除數據庫

'database模塊'

const mongoose = require('mongoose');
module.exports = new Promise((resolve, reject) => {
    mongoose.connect('mongodb://localhost:27017/userinfos', { useCreateIndex: true, useNewUrlParser: true });
    mongoose.connection.once('open', err => {
        if (!err) {
            console.log('數據庫鏈接成功')
            resolve()
        } else {
            console.log('數據庫鏈接失敗', err)
            reject(err)
        }
    })
})

------

'model對象模塊'
 '這裏定義限制對象時,必定要考慮好, 不然數據庫鏈接啓動後,除非刪除數據庫, 否則沒法修改限制對象的內容!!!!'
const { Schema, model } = require('mongoose');
const ajaxschema = new Schema({
    username: {
        type: String,
        unique: true,
        required: true
    },
    password: {
        type: String,
        required: true
    },
    email: {
        type: String,
        unique: true,
        required: true
    },
})
const model1 = model('userinfo', ajaxschema);
module.exports = model1;

複製代碼

6、 ejs 的渲染目錄

  • ejs的渲染數據在ejs文件中的格式有三種
  • 1.<% data %>裏面能夠寫任意代碼
  • 2.<%= data %> 裏面寫的代碼最終會轉義後再出現(推薦)
  • 3.<%- data %>裏面寫的代碼最終不會轉義後就出現(不安全)
'index.ejs '


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>歡迎來到首頁</h1>
    <a href="http://localhost:8080/login">登錄</a>
    <a href="http://localhost:8080/register">註冊</a>
    <a href="http://localhost:8080/usercenter">我的中心</a>
</body>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script>

</script>

</html>

-------


'login.ejs'

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form method="post" action="/login">
        <label for="username">用戶名</label>
        <input type="text" name="username" value=<%= err.username %>><%= err.usernameloginerr %> <br />
        <label for="password">密碼</label>
        <input type="password" value="" name="password">
        <input type="submit" id="sub">
    </form>
    <a href='/reset'>找回密碼</a> 
</body>
<script>
   
</script>

</html>

------------



'register.ejs'


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <form method="post" action="/register">
        <label for="usern ame">用戶名</label>
        <input type="text"name="username"  value= <%=  err.username  %> > <%=  err.usernamereerr  %></br>
        <label for="password">密碼</label>
        <input type="password" value="" name="password"> <%=  err.passworderr  %></br>
        <label for="repassword">再次確認密碼</label>
        <input type="password" value="" name="repassword"> <%=  err.repassworderr  %></br>
        <label for="email">郵箱</label>
        <input type="text"  name="email" value= <%= err.email %> > <%=  err.emailerr  %></br>
        <input type="submit">
    </form>
</body>

</html>


-----------



'reset.ejs'

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form method="post" action="/reset">
        <label for="usern ame">您註冊的用戶名</label>
        <input type="text" name="username" value=<%=  err.username  %>> <%=  err.usernamereerr  %></br>
        <label for="password">重置後的密碼</label>
        <input type="password" value="" name="password"> <%=  err.passworderr  %></br>
        <label for="repassword">請再次確認密碼</label>
        <input type="password" value="" name="repassword"> <%=  err.repassworderr  %></br>
        <label for="email">您的註冊郵箱</label>
        <input type="text" name="email" value=<%= err.email %>> <%=  err.emailerr  %></br>
        <input type="submit">
    </form>
</body>

</html>


------



'usercenter.ejs'


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>歡迎來到我的中心</h1>
    <a href="/index">返回主頁</a>
</body>
</html>

------
複製代碼

7、後期會放一波 TypeScript 重構項目的源碼,目前還須要調試。

相關文章
相關標籤/搜索