Node.js学习笔记----day04之学生信息管理系统

认真学习,认真记录,每天都要有进步呀!!!
加油叭!!!


一、起步

项目结构

在这里插入图片描述

  1. 安装需要的包
    在这里插入图片描述
  2. 初始化显示index.html

index.html

var express = require('express') var app = express() app.use('/node_modules/', express.static('./node_modules/')) app.use('/public/', express.static('./public/')) app.engine('html', require('express-art-template')) app.get('/',function (req,res) { res.render('index.html',{ fruit:[ '苹果', '香蕉', '橘子' ] }) }) app.listen(3000, function () { console.log('running 3000...') })
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 container"> <h2 class="sub-header">学生信息系统</h2> <a class="btn btn-success" href="/students/new">添加学生</a> <table class="table"> <thead class="thead-light"> <tr> <th scope="col">#</th> {{each fruit}} <th scope="col">{{$value}}</th> {{/each}} <!-- <th scope="col">First</th> <th scope="col">Last</th> <th scope="col">Handle</th> --> </tr> </thead> <tbody> <tr> <th scope="row">1</th> <td>Mark</td> <td>Otto</td> <td>@mdo</td> </tr> <tr> <th scope="row">2</th> <td>Jacob</td> <td>Thornton</td> <td>@fat</td> </tr> <tr> <th scope="row">3</th> <td>Larry</td> <td>the Bird</td> <td>@twitter</td> </tr> </tbody> </table> </div> </body> </html>

来吧展示:

在这里插入图片描述

二、从文件中读取数据

  1. 直接写入json数据渲染页面
    app.js
app.get('/',function (req,res) { res.render('index.html',{ // fruit:[ // '苹果', // '香蕉', // '橘子', // ] students:[ {"id":1,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"}, {"id":2,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"}, {"id":3,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"}, {"id":4,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"}, {"id":5,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"}, {"id":6,"name":"张三","gender":0,"age":18,"hobbies":"吃饭,睡觉,打豆豆"} ] }) })

index.html

<table class="table"> <thead class="thead-light"> <tr> <th scope="col">id</th> <th scope="col">姓名</th> <th scope="col">性别</th> <th scope="col">年龄</th> <th scope="col">兴趣</th> </tr> </thead> <tbody> {{each students}} <tr> <th scope="row">{{$value.id}}</th> <td>{{$value.name}}</td> <td>{{$value.gender}}</td> <td>{{$value.age}}</td> <td>{{$value.hobbies}}</td> </tr> {{/each}} </tbody> </table>

来吧展示:

在这里插入图片描述
2. 通过fs.readFile()读取db.json文件渲染页面

var fs = require('fs') fs.readFile('./db.json','utf8',function(err,data){ if(err){ return res.status(500).send('Server error...') } console.log(data) })

打印结果是:
在这里插入图片描述

在这里插入图片描述

app.get('/',function (req,res) { fs.readFile('./db.json','utf8',function(err,data){ if(err){ return res.status(500).send('Server error...') } res.render('index.html',{ students:JSON.parse(data).students }) }) })

在这里插入图片描述

三、设计路由

请求方法 请求路径 get 参数 post 参数 备注
GET /studens 渲染首页
GET /students/new 渲染添加学生页面
POST /studens/new name、age、gender、hobbies 处理添加学生请求
GET /students/edit id 渲染编辑页面
POST /studens/edit id、name、age、gender、hobbies 处理编辑请求
GET /students/delete id 处理删除请求

四、把路由都挂载到路由容器中

路由模块的职责
处理路由,根据不同的请求方法 + 路径设置具体的请求处理函数
模块职责要单一,不要乱写
划分模块的目的就是为了增加代码的可维护性,提高开发效率

方式一(不推荐):

在这里插入图片描述

当node执行app.js的时候,页面不能正常显示
在这里插入图片描述
当node执行router.js的时候,页面能正常显示

在这里插入图片描述
方式二(也不推荐)

在这里插入图片描述

在这里插入图片描述
方式三
Express提供了一种更好的方式,专门用来包装路由的

  1. 创建一个路由容器
var router = express.Router()
  1. 把路由都挂载到 router 路由容器中

  2. 把 router 导出

module.exports = router
  1. 把路由容器挂载到 app 服务中
app.use(router)

在这里插入图片描述

来吧展示:

在这里插入图片描述

整合一下 router.js

var fs = require('fs') var express = require('express') //1. 创建一个路由容器 var router = express.Router() //2. 把路由都挂载到 router 路由容器中 router.get('/students',function (req,res) { fs.readFile('./db.json','utf8',function(err,data){ if(err){ return res.status(500).send('Server error...') } res.render('index.html',{ students:JSON.parse(data).students }) }) }) router.get('/students/new',function (req,res) { }) router.post('/students/new',function (req,res) { }) router.get('/students/edit',function (req,res) { }) router.post('/students/edit',function (req,res) { }) router.get('/students/delete',function (req,res) { }) //3. 把 router 导出 module.exports = router

五、处理添加页面以及配置body-parse

  1. 点击添加学生跳转添加页面
    inde.html
<a class="btn btn-success" href="/students/new">添加学生</a>
  1. 渲染添加学生页面

router.js

router.get('/students/new', function (req, res) { res.render('new.html') })
  1. new.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <h2 class="sub-header">添加学生</h2> <form action="/students/new" method="post"> <div class="form-group"> <label for="">姓名</label> <input type="text" class="form-control" id="" name="name" required minlength="2" maxlength="10"> </div> <div class="form-group"> <label for="">性别</label> <div> <label class="radio-inline"> <input type="radio" name="gender" id="" value="0" checked> </label> <label class="radio-inline"> <input type="radio" name="gender" id="" value="1"> </label> </div> </div> <div class="form-group"> <label for="">年龄</label> <input class="form-control" type="number" id="" name="age" required min="1" max="150"> </div> <div class="form-group"> <label for="">爱好</label> <input class="form-control" type="text" id="" name="hobbies"> </div> <button type="submit" class="btn btn-success">添加</button> </form> </div> </div> </body> </html>
  1. 安装body-parser中间件
    在这里插入图片描述
  2. 配置中间件
    app.js
//引入包 var bodyParser = require('body-parser') // 配置模板引擎和 body-parser 一定要在 app.use(router) 挂载路由之前 // parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })) // parse application/json app.use(bodyParser.json()) // 把路由容器挂载到 app 服务中 app.use(router)
  1. 查看是否能接收数据
router.get('/students/new', function (req, res) { res.render('new.html') }) router.post('/students/new',function (req,res) { console.log(req.body) })

来吧展示:

在这里插入图片描述
7. 将数据存入db.json文件用以持久化
先读取出来,转成对象,
然后往数据中push数据
然后将对象转成字符串
然后将字符串再次写入文件

六、封装提取Student数据操作模块

students.js

数据操作文件模块
职责:操作文件中的数据,只处理数据,不关心业务

var fs = require('fs') var dbPath = './db.json' exports.find = function (callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } callback(null, JSON.parse(data).students) }) }

router.js

var Student = require('./student') router.get('/students', function (req, res) { Student.find(function (err, students) { if (err) { return res.status(500).send('Server error.') } res.render('index.html', { students: students }) }) })

七、封装保存学生的API

student.js

exports.save = function (student, callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students // 添加 id ,唯一不重复 student.id = students[students.length - 1].id + 1 // 把用户传递的对象保存到数组中 students.push(student) // 把对象数据转换为字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存到文件中 fs.writeFile(dbPath, fileData, function (err) { if (err) { // 错误就是把错误对象传递给它 return callback(err) } // 成功就没错,所以错误对象是 null callback(null) }) }) }
//处理添加学生 router.post('/students/new', function (req, res) { // 1. 获取表单数据 // 2. 处理 // 将数据保存到 db.json 文件中用以持久化 // 3. 发送响应 Student.save(req.body, function (err) { if (err) { return res.status(500).send('Server error.') } res.redirect('/students') }) })

来吧展示:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

八、完成渲染编辑学生页面

  1. index.html中添加编辑和删除的标签并跳转到相应的页面
<tr> <th scope="col">id</th> <th scope="col">姓名</th> <th scope="col">性别</th> <th scope="col">年龄</th> <th scope="col">兴趣</th> <th scope="col">操作</th> </tr>
<tbody> {{each students}} <tr> <th scope="row">{{$value.id}}</th> <td>{{$value.name}}</td> <td>{{$value.gender}}</td> <td>{{$value.age}}</td> <td>{{$value.hobbies}}</td> <td> <a href="/students/edit?id={{ $value.id }}">编辑</a> <a href="/students/delete?id={{ $value.id }}">删除</a> </td> </tr> {{/each}} </tbody>
  1. edit.htmlnew.html文件大致相同
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <h2 class="sub-header">编辑学生</h2> <form action="/students/edit" method="post"> <!-- 用来放一些不希望被用户看见,但是需要被提交到服务端的数据 --> <input type="hidden" name="id" value="{{ student.id }}"> <div class="form-group"> <label for="">姓名</label> <input type="text" class="form-control" id="" name="name" required minlength="2" maxlength="10" value="{{ student.name }}"> </div> <div class="form-group"> <label for="">性别</label> <div> <label class="radio-inline"> <input type="radio" name="gender" id="" value="0" checked> </label> <label class="radio-inline"> <input type="radio" name="gender" id="" value="1"> </label> </div> </div> <div class="form-group"> <label for="">年龄</label> <input class="form-control" type="number" id="" name="age" required min="1" value="{{ student.age }}" max="150"> </div> <div class="form-group"> <label for="">爱好</label> <input class="form-control" type="text" id="" value="{{ student.hobbies }}" name="hobbies"> </div> <button type="submit" class="btn btn-success">添加</button> </form> </div> </div> </body> </html>
  1. 根据id去获取想要查找的学生信息
exports.findById = function (id, callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students var ret = students.find(function (item) { return item.id === parseInt(id) }) callback(null, ret) }) }
  1. 渲染编辑学生页面
router.get('/students/edit', function (req, res) { // 1. 在客户端的列表页中处理链接问题(需要有 id 参数) // 2. 获取要编辑的学生 id // // 3. 渲染编辑页面 // 根据 id 把学生信息查出来 // 使用模板引擎渲染页面 Student.findById(parseInt(req.query.id), function (err, student) { if (err) { return res.status(500).send('Server error.') } res.render('edit.html', { student: student }) }) })
  1. 封装添加保存学生函数
exports.updateById = function (student, callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students // 注意:这里记得把 id 统一转换为数字类型 student.id = parseInt(student.id) // 你要修改谁,就需要把谁找出来 // EcmaScript 6 中的一个数组方法:find // 需要接收一个函数作为参数 // 当某个遍历项符合 item.id === student.id 条件的时候,find 会终止遍历,同时返回遍历项 var stu = students.find(function (item) { return item.id === student.id }) // 这种方式比较麻烦 // stu.name = student.name // stu.age = student.age // 遍历拷贝对象 for (var key in student) { stu[key] = student[key] } // 把对象数据转换为字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存到文件中 fs.writeFile(dbPath, fileData, function (err) { if (err) { // 错误就是把错误对象传递给它 return callback(err) } // 成功就没错,所以错误对象是 null callback(null) }) }) }
  1. 处理编辑学生保存数据跳转到首页
router.post('/students/edit', function (req, res) { // 1. 获取表单数据 // req.body // 2. 更新 // Student.updateById() // 3. 发送响应 Student.updateById(req.body, function (err) { if (err) { return res.status(500).send('Server error.') } res.redirect('/students') }) })

来吧展示:

在这里插入图片描述
在这里插入图片描述

九、完成删除功能

在这里插入图片描述

exports.deleteById = function (id, callback) { fs.readFile(dbPath, 'utf8', function (err, data) { if (err) { return callback(err) } var students = JSON.parse(data).students // findIndex 方法专门用来根据条件查找元素的下标 var deleteId = students.findIndex(function (item) { return item.id === parseInt(id) }) // 根据下标从数组中删除对应的学生对象 students.splice(deleteId, 1) // 把对象数据转换为字符串 var fileData = JSON.stringify({ students: students }) // 把字符串保存到文件中 fs.writeFile(dbPath, fileData, function (err) { if (err) { // 错误就是把错误对象传递给它 return callback(err) } // 成功就没错,所以错误对象是 null callback(null) }) }) }
router.get('/students/delete', function (req, res) { // 1. 获取要删除的 id // 2. 根据 id 执行删除操作 // 3. 根据操作结果发送响应数据 Student.deleteById(req.query.id, function (err) { if (err) { return res.status(500).send('Server error.') } res.redirect('/students') }) })

来吧展示:

在这里插入图片描述
在这里插入图片描述


__EOF__

本文作者杨芋可可
本文链接https://www.cnblogs.com/yangyukeke/p/13823145.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   杨芋可可  阅读(355)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示