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);