Node教程——Node+MongoDB案例實現用戶資訊的增刪改查
- 2020 年 4 月 8 日
- 筆記
想要獲取源程式碼的同學可以留言,我不做git上傳了,案例太簡單 沒必要
綜合演練 用戶資訊的增刪改查
需求:你需要實現這樣的結果
點擊添加可以添加用戶,點擊刪除可以刪除點擊修改可以修改
程式碼分析:
1.搭建網站伺服器,實現客戶端與伺服器端的通訊
2.連接資料庫,創建用戶集合,向集合中插入文檔
3.當用戶訪問/list時,將所有用戶資訊查詢出來
4.將用戶資訊和表格HTML進行拼接並將拼接結果響應回客戶端
5.當用戶訪問/add時,呈現表單頁面,並實現添加用戶資訊功能
6.當用戶訪問/modify時,呈現修改頁面,並實現修改用戶資訊功能
7.當用戶訪問/delete時,實現用戶刪除功能
搭建文件夾結構
- 搭建伺服器,建立起通訊
const url = require('url'); const querystring = require('querystring'); const http = require('http') const app = http.createServer(); app.on('request', (req, res) => { res.end('ok') }) app.listen(3000)
- 鏈接資料庫
// 1.先創建 const mongoose = require('mongoose'); // 資料庫連接 27017是mongodb資料庫的默認埠 mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true }) .then(() => console.log('資料庫連接成功')) .catch(() => console.log('資料庫連接失敗')); // 2. 創建用戶集合規則,定義驗證 const userSchema = new mongoose.Schema({ name: { type: String, required: true, minlength: 2, maxlength: 20 }, age: { type: Number, min: 18, max: 80 }, password: String, email: String, hobbies: [String] }); // 創建集合 返回集合構造函數,並且拿到最重要的的東西----集合構造函數 const User = mongoose.model('User', userSchema); //別忘記了我們導入一些文件在user.json中 // 命令行操作也許gui操作也可以,你喜歡就好
- 實現路由,把數據拿出來渲染出來
程式碼比較多,但是它的業務邏輯是非常簡單的
//這個裡面的async app.on('request', async(req, res) => { const method = req.method; const { pathname, query } = url.parse(req.url, true); //注意整理的${item._id}都是獲取瀏覽器請求的字元串解析 if (method == 'GET') { //注意這裡的get方式 // 呈現用戶列表頁面-數據是一點一點的拼接 if (pathname == '/list') { // 查詢用戶資訊 let users = await User.find(); //返回的是一個資料庫數組 // html字元串 let list = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h6> <a href="/add" class="btn btn-primary">添加用戶</a> </h6> <table class="table table-striped table-bordered"> <tr> <td>用戶名</td> <td>年齡</td> <td>愛好</td> <td>郵箱</td> <td>操作</td> </tr> `; // 對數據進行循環操作 users.forEach(item => { //注意這個東西 item是一個一個數組對象,它是從 users finde從資料庫找來的 list += ` <tr> <td>${item.name}</td> <td>${item.age}</td> <td> `; //這個比較特殊,愛好是數組中的數組,所有我們需要多層的循環 item.hobbies.forEach(item => { list += `<span>${item}</span>`; }) list += `</td> <td>${item.email}</td> <td> <a href="/remove?id=${item._id}" class="btn btn-danger btn-xs">刪除</a> <a href="/modify?id=${item._id}" class="btn btn-success btn-xs">修改</a> </td> </tr>`; }); list += ` </table> </div> </body> </html> `; res.end(list); } else if (pathname == '/add') { // 呈現添加用戶表單頁面 let add = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h3>添加用戶</h3> <form method="post" action="/add"> <div class="form-group"> <label>用戶名</label> <input name="name" type="text" class="form-control" placeholder="請填寫用戶名"> </div> <div class="form-group"> <label>密碼</label> <input name="password" type="password" class="form-control" placeholder="請輸入密碼"> </div> <div class="form-group"> <label>年齡</label> <input name="age" type="text" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>郵箱</label> <input name="email" type="email" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>請選擇愛好</label> <div> <label class="checkbox-inline"> <input type="checkbox" value="足球" name="hobbies"> 足球 </label> <label class="checkbox-inline"> <input type="checkbox" value="籃球" name="hobbies"> 籃球 </label> <label class="checkbox-inline"> <input type="checkbox" value="橄欖球" name="hobbies"> 橄欖球 </label> <label class="checkbox-inline"> <input type="checkbox" value="敲程式碼" name="hobbies"> 敲程式碼 </label> <label class="checkbox-inline"> <input type="checkbox" value="抽煙" name="hobbies"> 抽煙 </label> <label class="checkbox-inline"> <input type="checkbox" value="喝酒" name="hobbies"> 喝酒 </label> <label class="checkbox-inline"> <input type="checkbox" value="燙頭" name="hobbies"> 燙頭 </label> </div> </div> <button type="submit" class="btn btn-primary">添加用戶</button> </form> </div> </body> </html> `; res.end(add) // } else if (pathname == '/modify') { let user = await User.findOne({ _id: query.id }); //通過id拿到數據 let hobbies = ['足球', '籃球', '橄欖球', '敲程式碼', '抽煙', '喝酒', '燙頭', '吃飯', '睡覺', '打豆豆'] console.log(user) // 呈現修改用戶表單頁面 let modify = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h3>修改用戶</h3> <form method="post" action="/modify?id=${user._id}"> <div class="form-group"> <label>用戶名</label> <input value="${user.name}" name="name" type="text" class="form-control" placeholder="請填寫用戶名"> </div> <div class="form-group"> <label>密碼</label> <input value="${user.password}" name="password" type="password" class="form-control" placeholder="請輸入密碼"> </div> <div class="form-group"> <label>年齡</label> <input value="${user.age}" name="age" type="text" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>郵箱</label> <input value="${user.email}" name="email" type="email" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>請選擇愛好</label> <div> `; //這個是愛好的寫法,這裡還是有點特殊的,循環的判斷 hobbies.forEach(item => { // 判斷當前循環項在不在用戶的愛好數據組 let isHobby = user.hobbies.includes(item); if (isHobby) { modify += ` <label class="checkbox-inline"> <input type="checkbox" value="${item}" name="hobbies" checked> ${item} </label> ` //這裡有兩個是不一樣的,愛好的複選框,呈遞你選擇的數據修改頁 } else { modify += ` <label class="checkbox-inline"> <input type="checkbox" value="${item}" name="hobbies"> ${item} </label> ` } }) modify += ` </div> </div> <button type="submit" class="btn btn-primary">修改用戶</button> </form> </div> </body> </html> `; res.end(modify) } else if (pathname == '/remove') { // res.end(query.id) await User.findOneAndDelete({ _id: query.id }); res.writeHead(301, { Location: '/list' }); res.end(); } //另外一個post路由 } else if (method == 'POST') { //這裡是的是post方式 // 用戶添加功能 if (pathname == '/add') { // 接受用戶提交的資訊 let formData = ''; // 接受post參數是一步一步的接收的, req.on('data', param => { formData += param; }) // post參數接受完畢 req.on('end', async() => { let user = querystring.parse(formData) //解析格式 // 將用戶提交的資訊添加到資料庫中 await User.create(user); // 301代表重定向 // location 跳轉地址 res.writeHead(301, { Location: '/list' }); res.end(); }) } else if (pathname == '/modify') { // 接受用戶提交的資訊 let formData = ''; // 接受post參數 req.on('data', param => { formData += param; }) // post參數接受完畢 req.on('end', async() => { let user = querystring.parse(formData) // 將用戶提交的資訊添加到資料庫中 await User.updateOne({ _id: query.id }, user); // 301代表重定向 // location 跳轉地址 res.writeHead(301, { Location: '/list' }); res.end(); }) } } });
- 把模組分離出來
下面是uers.js的程式碼,完成創建
//從app.js抽取中出來 const mongoose = require('mongoose'); // 創建用戶集合規則 const userSchema = new mongoose.Schema({ name: { type: String, required: true, minlength: 2, maxlength: 20 }, age: { type: Number, min: 18, max: 80 }, password: String, email: String, hobbies: [String] }); // 創建集合 返回集合構造函數 const User = mongoose.model('User', userSchema); //之前講node基礎的時候就講過:開放某一部分的參數,這個參數可以是函數 module.exports = User;//把東西開放出去
下面的是index.js程式碼,完成資料庫連接
//從app.js抽取中出來 const mongoose = require('mongoose'); // 資料庫連接 27017是mongodb資料庫的默認埠 mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true }) .then(() => console.log('資料庫連接成功')) .catch(() => console.log('資料庫連接失敗'));
下面的是app.js
// 搭建網站伺服器,實現客戶端與伺服器端的通訊 // 連接資料庫,創建用戶集合,向集合中插入文檔 // 當用戶訪問/list時,將所有用戶資訊查詢出來 // 實現路由功能 // 呈現用戶列表頁面 // 從資料庫中查詢用戶資訊 將用戶資訊展示在列表中 // 將用戶資訊和表格HTML進行拼接並將拼接結果響應回客戶端 // 當用戶訪問/add時,呈現表單頁面,並實現添加用戶資訊功能 // 當用戶訪問/modify時,呈現修改頁面,並實現修改用戶資訊功能 // 修改用戶資訊分為兩大步驟 // 1.增加頁面路由 呈現頁面 // 1.在點擊修改按鈕的時候 將用戶ID傳遞到當前頁面 // 2.從資料庫中查詢當前用戶資訊 將用戶資訊展示到頁面中 // 2.實現用戶修改功能 // 1.指定表單的提交地址以及請求方式 // 2.接受客戶端傳遞過來的修改資訊 找到用戶 將用戶資訊更改為最新的 // 當用戶訪問/delete時,實現用戶刪除功能 const http = require('http'); const url = require('url'); const querystring = require('querystring'); //重新引入抽離出去的程式碼 require('./model/index.js'); const User = require('./model/user'); // 創建伺服器 const app = http.createServer(); // 為伺服器對象添加請求事件 app.on('request', async(req, res) => { // 請求方式 const method = req.method; // 請求地址,query是保存了一些get和post屬性,後面的true是把它變成一個對象 const { pathname, query } = url.parse(req.url, true); //注意整理的${item._id}都是獲取瀏覽器請求的字元串解析 if (method == 'GET') { //注意這裡的get方式 // 呈現用戶列表頁面-數據是一點一點的拼接 if (pathname == '/list') { // 查詢用戶資訊 let users = await User.find(); //返回的是一個資料庫數組 // html字元串 let list = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h6> <a href="/add" class="btn btn-primary">添加用戶</a> </h6> <table class="table table-striped table-bordered"> <tr> <td>用戶名</td> <td>年齡</td> <td>愛好</td> <td>郵箱</td> <td>操作</td> </tr> `; // 對數據進行循環操作 users.forEach(item => { //注意這個東西 item是一個一個數組對象,它是從 users finde從資料庫找來的 list += ` <tr> <td>${item.name}</td> <td>${item.age}</td> <td> `; //這個比較特殊,愛好是數組中的數組,所有我們需要多層的循環 item.hobbies.forEach(item => { list += `<span>${item}</span>`; }) list += `</td> <td>${item.email}</td> <td> <a href="/remove?id=${item._id}" class="btn btn-danger btn-xs">刪除</a> <a href="/modify?id=${item._id}" class="btn btn-success btn-xs">修改</a> </td> </tr>`; }); list += ` </table> </div> </body> </html> `; res.end(list); } else if (pathname == '/add') { // 呈現添加用戶表單頁面 let add = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h3>添加用戶</h3> <form method="post" action="/add"> <div class="form-group"> <label>用戶名</label> <input name="name" type="text" class="form-control" placeholder="請填寫用戶名"> </div> <div class="form-group"> <label>密碼</label> <input name="password" type="password" class="form-control" placeholder="請輸入密碼"> </div> <div class="form-group"> <label>年齡</label> <input name="age" type="text" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>郵箱</label> <input name="email" type="email" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>請選擇愛好</label> <div> <label class="checkbox-inline"> <input type="checkbox" value="足球" name="hobbies"> 足球 </label> <label class="checkbox-inline"> <input type="checkbox" value="籃球" name="hobbies"> 籃球 </label> <label class="checkbox-inline"> <input type="checkbox" value="橄欖球" name="hobbies"> 橄欖球 </label> <label class="checkbox-inline"> <input type="checkbox" value="敲程式碼" name="hobbies"> 敲程式碼 </label> <label class="checkbox-inline"> <input type="checkbox" value="抽煙" name="hobbies"> 抽煙 </label> <label class="checkbox-inline"> <input type="checkbox" value="喝酒" name="hobbies"> 喝酒 </label> <label class="checkbox-inline"> <input type="checkbox" value="燙頭" name="hobbies"> 燙頭 </label> </div> </div> <button type="submit" class="btn btn-primary">添加用戶</button> </form> </div> </body> </html> `; res.end(add) // } else if (pathname == '/modify') { let user = await User.findOne({ _id: query.id }); //通過id拿到數據 let hobbies = ['足球', '籃球', '橄欖球', '敲程式碼', '抽煙', '喝酒', '燙頭', '吃飯', '睡覺', '打豆豆'] console.log(user) // 呈現修改用戶表單頁面 let modify = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用戶列表</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> </head> <body> <div class="container"> <h3>修改用戶</h3> <form method="post" action="/modify?id=${user._id}"> <div class="form-group"> <label>用戶名</label> <input value="${user.name}" name="name" type="text" class="form-control" placeholder="請填寫用戶名"> </div> <div class="form-group"> <label>密碼</label> <input value="${user.password}" name="password" type="password" class="form-control" placeholder="請輸入密碼"> </div> <div class="form-group"> <label>年齡</label> <input value="${user.age}" name="age" type="text" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>郵箱</label> <input value="${user.email}" name="email" type="email" class="form-control" placeholder="請填寫郵箱"> </div> <div class="form-group"> <label>請選擇愛好</label> <div> `; //這個是愛好的寫法,這裡還是有點特殊的,循環的判斷 hobbies.forEach(item => { // 判斷當前循環項在不在用戶的愛好數據組 let isHobby = user.hobbies.includes(item); if (isHobby) { modify += ` <label class="checkbox-inline"> <input type="checkbox" value="${item}" name="hobbies" checked> ${item} </label> ` //這裡有兩個是不一樣的,愛好的複選框,呈遞你選擇的數據修改頁 } else { modify += ` <label class="checkbox-inline"> <input type="checkbox" value="${item}" name="hobbies"> ${item} </label> ` } }) modify += ` </div> </div> <button type="submit" class="btn btn-primary">修改用戶</button> </form> </div> </body> </html> `; res.end(modify) } else if (pathname == '/remove') { // res.end(query.id) await User.findOneAndDelete({ _id: query.id }); res.writeHead(301, { Location: '/list' }); res.end(); } //另外一個post路由 } else if (method == 'POST') { //這裡是的是post方式 // 用戶添加功能 if (pathname == '/add') { // 接受用戶提交的資訊 let formData = ''; // 接受post參數是一步一步的接收的, req.on('data', param => { formData += param; }) // post參數接受完畢 req.on('end', async() => { let user = querystring.parse(formData) //解析格式 // 將用戶提交的資訊添加到資料庫中 await User.create(user); // 301代表重定向 // location 跳轉地址 res.writeHead(301, { Location: '/list' }); res.end(); }) } else if (pathname == '/modify') { // 接受用戶提交的資訊 let formData = ''; // 接受post參數 req.on('data', param => { formData += param; }) // post參數接受完畢 req.on('end', async() => { let user = querystring.parse(formData) // 將用戶提交的資訊添加到資料庫中 await User.updateOne({ _id: query.id }, user); // 301代表重定向 // location 跳轉地址 res.writeHead(301, { Location: '/list' }); res.end(); }) } } }); // 監聽埠 app.listen(3000);