node学习(三) -- 经典 CRUD 操作
制作一个管理系统的小 Demo
1. 搭建目录结构
创建 public
公共资源文件夹、views
视图资源文件夹,app.js
入口文件
├─ crud-express
│ ├─ app.js
│ ├─ package.json
│ ├─ public
│ ├─ views
│ └─ yarn.lock
引入 express
模块,启动一个基本服务
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("hello world");
});
app.listen(3000, () => {
console.log("服务已经在3000端口启动...");
});
2. 引入 BootStrap 模板
// bootStrap 模板地址
https://v3.bootcss.com/examples/dashboard/
大致样式如上
利用 render
渲染页面,简单测试一下模板是否正常使用
res.render("index.html", {
fruits: ["苹果", "香蕉", "鞠总"],
});
并且在页面内添加一个 添加学生
按钮
雏形已经基本呈现
3. 准备数据
在本地新建 db.json
文件,准备假数据,我们先利用假数据进行开发,最后再加入数据库操作
一个简单的数据列表
4. 渲染数据
我们需要将我们的数据渲染到文件上
这一步很简单,通过模板引擎几步就能实现
在这些之前,我们先更改页面样式,让他符合我们的学生管理系统
<tr>
<th>学号id</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>爱好</th>
</tr>
将内容切换成我们需要显示的标题
从文件中读取出数据
这里我们需要引入一个 fs
文件读取模块
const fs = require("fs");
然后我们需要在 render
之前进行文件的读取,将获取到的数据传给 student
变量来保存
fs.readFile("./db.json", "utf8", (err, data) => {
if (err) {
res.status(500).send("Server error");
}
});
这里需要注意的是,我们读取文件返回的是一个字符串,我们需要对返回的数据进行处理才能使用,有两种处理方法
readFile
的第二个参数是可选的,我们可以传入utf8
,指示它将文件直接按照utf8
编码显示- 还可以通过
data.toSting
方法对数据进行处理
我们在终端输出一下我们读取到的数据data
可以看到输出的是一个 JSON
字符串,没有对象的功能,我们需要通过 parse
方法将它转化为一个对象
res.render("index.html", {
students: JSON.parse(data).students,
});
注意,这里因为我们的数据中,包了一层
students
对象,所以我们需要再获取一层
这样,我们就能将一个 student
对象作为模板数据进行渲染
{{each students}}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.name}}</td>
<td>{{$value.gender}}</td>
<td>{{$value.age}}</td>
<td>{{$value.hobbies}}</td>
</tr>
{{/each}}
这样,我们的数据就成功的渲染到页面上了
5. 路由设计
请求方法 | 请求路径 | 携带参数 | 作用 |
---|---|---|---|
GET | /students | 渲染首页 | |
GET | /students/new | 渲染添加学生页面 | |
POST | /students | name、age、gender、hobbies, | 添加学生数据 |
GET | /students/edit | id | 渲染编辑页面 |
POST | /students/edit | id、name、age、gender、hobbies | 处理编辑请求 |
GET | /students/delete | id | 处理删除请求 |
注意:express
中的请求路径也不包含查询字符串,如果我们采用 /student?id=asdfa
来发送编辑请求,会被 /students
先捕获
6. 路由模块引入
看到上面的路由设计表,如果我们还将全部的请求写在 app.js
中,app.js
中的代码就会很杂很多,因此我们把这些请求全部放到一个 router.js
文件中
// 示例 router.js
app.get("/students/new",(req,res)=>{
})
app.get("/students/new",(req,res)=>{
})
app.get("/students/new",(req,res)=>{
但是我们需要保证 app.js
文件依旧是入口文件,因此我们不能将 app
模块导入 router.js
中
首先我们需要对 router.js
利用函数包裹,再导出
router.js
完整代码如下
然后,我们需要在 app.js
中引入这个文件
const router = require('./router')
由于我们在 router.js
中暴露的是一个函数,因此我们可以向他传递一个参数
我们将 app
传递给它,这样在 router.js
中就可以使用 app
模块了
router(app);
由于我们也使用了 fs
模块,我们也可以传递两个参数
router(app, fs);
但是这种方式还是很麻烦,express 给我们提供了一个更好的方式
最优解
利用 express
给我提供的 router
容器来实现
第一步:我们需要创建一个路由容器
const router = express.Router();
第二步:把路由挂载在 Router 中
通过 router.
的方式完成挂载
router.get("/students/new", (req, res) => {});
router.get("/students/new", (req, res) => {});
router.get("/students/new", (req, res) => {});
第三步:导出 router
module.exports = router;
第四步:在 app.js
中引入 router
const router = require("./router");
第五步:把路由容器挂载到 app 服务中
app.use(router);
注意:有些模块需要在 router 中引入哦
router.js
模块职责:根据不同的请求方式路径,配置请求处理函数
模块职责单一:增强可维护性,方便代码书写
7. 配置处理 post 请求中间件
app.use(express.urlencoded({ extended: false }));app.use(express.json());
配置模板引擎和 body-parser
一定要在 app.use(router)
挂载路由之前配置
这样我们就可以在 router.js
中编写响应处理函数
// 先简单的打印一下获取到的表单信息// -------------------处理新增请求---------------router.post("/students/new", (req, res) => { console.log(req.body);});
成功输出数据,对数据进行处理,写入我们的假数据文件中
8. 设计操作数据的 API 文件模块
// 获取所有学生列表exports.find = function () {};// 添加学生exports.save = function () {};// 更新学生exports.update = function () {};// 删除学习exports.delete = function () {};
9. 编写 find 方法
// 获取所有学生列表// callback 第一个参数是err 第二个是dataexports.find = function (callback) { fs.readFile(dbPath, "utf8", (err, data) => { if (err) { // 第一个参数接收错误对象 return callback(err); } callback(null, JSON.parse(data).students); });};
由于这里需要读取文件操作,这个操作是异步的,我们需要进行一定的处理
例如:采用 回调函数,promise ,async、await,都可以进行处理,这里采用的是回调函数的写法
我们在调用的时候需要传入一个函数来接收它的响应数据
Student.find((err, students) => { err && res.status(500).send("Server error"); res.render("index.html", { fruits: ["小丞", "同学", "好"], students: students, }); });
10. 编写 save 方法
读取文件中学生信息,处理数据,写入数据
- 将传入的学生信息添加 id 信息
- 写入
students
对象中 - 将对象转为 JSON 字符串
- 存入文件中
// 添加学生exports.save = function (student, callback) { fs.readFile(dbPath, "utf8", (err, data) => { // 处理错误 if (err) { return callback(err); } // 读取db中全部数据 let students = JSON.parse(data).students; // 添加 id student.id = students[students.length - 1].id + 1; console.log(student); // 解构新增数据 students = [...students, student]; // students.push(student); // 转成 JSON 字符串 let fileData = JSON.stringify({ students: students, }); // 写入文件 fs.writeFile(dbPath, fileData, (err) => { if (err) { return callback(err); } callback(null); }); });};
11. 编写 update 方法
需要查找学生 id
来更新对应学生数据
const stu = students.find((item) => (item.id = student.id));for (let key in student) { stu[key] = student[key];}
隐藏表单元素
<input type="hidden" id="{{student.id}}">
12. 操作mongodb数据库
只需要编写一个 schema
模板就好了
/* * @Author: 林俊丞 * @Date: 2021-09-16 19:36:58 * @LastEditors: 林俊丞 * @LastEditTime: 2021-09-16 20:10:24 * @Description: */const mongoose = require("mongoose");// 链接数据库mongoose.connect("mongodb://localhost:27017/test", { useNewUrlParser: true, useUnifiedTopology: true,});const Schema = mongoose.Schema;const StudentSchema = new Schema({ name: { type: String, required: true, }, gender: { type: Number, enum: [0, 1], default: 0, }, age: { type: Number, required: true, }, hobbies: { type: String, },});// 查找全部module.exports = mongoose.model("Student", StudentSchema);
更改一下 router
中的函数调用 API
13. 采用认证方式操作数据库
mongoose.connect("mongodb://admin:123456@120.78.221.14:27017/test?authSource=admin", { useNewUrlParser: true, useUnifiedTopology: true,});
mongodb://'用户名':'密码'@'地址'/'数据库'?authSource='用户所在数据库'
14. 配置跨域
// 配置跨域app.all("*", function (req, res, next) { //设置允许跨域的域名,*代表允许任意域名跨域 res.header("Access-Control-Allow-Origin", "*"); //允许的header类型 res.header("Access-Control-Allow-Headers", "content-type"); //跨域允许的请求方式 res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS"); if (req.method.toLowerCase() == "options") res.send(200); //让options尝试请求快速结束 else next();});
15. 使用 MD5 进行加密
首先安装 md5
yarn add js-md5
引入
import md5 from 'js-md5'
使用
const d = md5(password)
- 点赞
- 收藏
- 关注作者
评论(0)