node学习(三) -- 经典 CRUD 操作

举报
阿童木 发表于 2021/10/25 15:17:05 2021/10/25
【摘要】 制作一个管理系统的小 Demo 1. 搭建目录结构创建 public 公共资源文件夹、views 视图资源文件夹,app.js 入口文件├─ crud-express│ ├─ app.js│ ├─ package.json│ ├─ public│ ├─ views│ └─ yarn.lock引入 express 模块,启动一个基本服务const express = require(...

制作一个管理系统的小 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/

image-20210915215636172

大致样式如上

利用 render 渲染页面,简单测试一下模板是否正常使用

res.render("index.html", {
    fruits: ["苹果", "香蕉", "鞠总"],
});

并且在页面内添加一个 添加学生 按钮

image-20210915221200197

雏形已经基本呈现

3. 准备数据

在本地新建 db.json 文件,准备假数据,我们先利用假数据进行开发,最后再加入数据库操作

一个简单的数据列表

image-20210915222118580

4. 渲染数据

我们需要将我们的数据渲染到文件上

这一步很简单,通过模板引擎几步就能实现

在这些之前,我们先更改页面样式,让他符合我们的学生管理系统

<tr>
  <th>学号id</th>
  <th>姓名</th>
  <th>性别</th>
  <th>年龄</th>
  <th>爱好</th>
</tr>

将内容切换成我们需要显示的标题

image-20210915222629062

从文件中读取出数据

这里我们需要引入一个 fs 文件读取模块

const fs = require("fs");

然后我们需要在 render 之前进行文件的读取,将获取到的数据传给 student 变量来保存

fs.readFile("./db.json", "utf8", (err, data) => {
if (err) {
    res.status(500).send("Server error");
}
});

这里需要注意的是,我们读取文件返回的是一个字符串,我们需要对返回的数据进行处理才能使用,有两种处理方法

  1. readFile 的第二个参数是可选的,我们可以传入 utf8 ,指示它将文件直接按照 utf8 编码显示
  2. 还可以通过 data.toSting 方法对数据进行处理

我们在终端输出一下我们读取到的数据data

image-20210915223822561

可以看到输出的是一个 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}}

image-20210915224724076

这样,我们的数据就成功的渲染到页面上了

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 完整代码如下

image-20210915230947231

然后,我们需要在 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 中引入哦

image-20210915232217246

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

image-20210916153821094

成功输出数据,对数据进行处理,写入我们的假数据文件中

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 方法

读取文件中学生信息,处理数据,写入数据

  1. 将传入的学生信息添加 id 信息
  2. 写入 students 对象中
  3. 将对象转为 JSON 字符串
  4. 存入文件中
// 添加学生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)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。