分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

node.js(小案例)_实现学生信息增删改

发布时间:2023-09-06 02:35责任编辑:苏小强关键词:js

一、前言

本节内容主要对小案例做一个总结:

1、如何开始搭建小项目

2、路由设计

3、模块应用

4、项目源码以及实现过程github地址:

项目演示如下:

二、主要内容

1、项目的关键性js源码:

项目的入口:

/** * app.js 入门模块 * 职责: * ??创建服务 * ??做一些服务相关配置 * ????模板引擎 * ????body-parser 解析表单 post 请求体 * ????提供静态资源服务 * ??挂载路由 * ??监听端口启动服务 */var express = require(‘express‘)var router = require(‘./router‘)var bodyParser = require(‘body-parser‘)var app = express()app.use(‘/node_modules/‘, express.static(‘./node_modules/‘))app.use(‘/public/‘, express.static(‘./public/‘))app.engine(‘html‘, require(‘express-art-template‘))// 配置模板引擎和 body-parser 一定要在 app.use(router) 挂载路由之前// parse application/x-www-form-urlencodedapp.use(bodyParser.urlencoded({ extended: false }))// parse application/jsonapp.use(bodyParser.json())// 把路由容器挂载到 app 服务中app.use(router)app.listen(3000, function () { ?console.log(‘running 3000...‘)})module.exports = app
app.js

路由设计模块:

/** * router.js 路由模块 * 职责: * ??处理路由 * ??根据不同的请求方法+请求路径设置具体的请求处理函数 * 模块职责要单一,不要乱写 * 我们划分模块的目的就是为了增强项目代码的可维护性 * 提升开发效率 */var fs = require(‘fs‘)var Student = require(‘./student‘)// Express 提供了一种更好的方式// 专门用来包装路由的var express = require(‘express‘)// 1. 创建一个路由容器var router = express.Router()// 2. 把路由都挂载到 router 路由容器中/* * 渲染学生列表页面 */router.get(‘/students‘, function (req, res) { ?Student.find(function (err, students) { ???if (err) { ?????return res.status(500).send(‘Server error.‘) ???} ???res.render(‘index.html‘, { ?????fruits: [ ???????‘苹果‘, ???????‘香蕉‘, ???????‘橘子‘ ?????], ?????students: students ???}) ?})})/* * 渲染添加学生页面 */router.get(‘/students/new‘, function (req, res) { ?res.render(‘new.html‘)})/* * 处理添加学生 */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‘) ?})})/* * 渲染编辑学生页面 */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 ???}) ?})})/* * 处理编辑学生 */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‘) ?})})/* * 处理删除学生 */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‘) ?})})// 3. 把 router 导出module.exports = router// 这样也不方便// module.exports = function (app) {// ??app.get(‘/students‘, function (req, res) {// ????// readFile 的第二个参数是可选的,传入 utf8 就是告诉它把读取到的文件直接按照 utf8 编码转成我们能认识的字符// ????// 除了这样来转换之外,也可以通过 data.toString() 的方式// ????fs.readFile(‘./db.json‘, ‘utf8‘, function (err, data) {// ??????if (err) {// ????????return res.status(500).send(‘Server error.‘)// ??????}// ??????// 从文件中读取到的数据一定是字符串// ??????// 所以这里一定要手动转成对象// ??????var students = JSON.parse(data).students// ??????res.render(‘index.html‘, {// ????????fruits: [// ??????????‘苹果‘,// ??????????‘香蕉‘,// ??????????‘橘子‘// ????????],// ????????students: students// ??????})// ????})// ??})// ??app.get(‘/students/new‘, function (req, res) {// ??})// ??app.get(‘/students/new‘, function (req, res) {// ??})// ??app.get(‘/students/new‘, function (req, res) {// ??})// ??app.get(‘/students/new‘, function (req, res) {// ??})// ??app.get(‘/students/new‘, function (req, res) {// ??})// }
View Code

功能实现模块

/** * student.js * 数据操作文件模块 * 职责:操作文件中的数据,只处理数据,不关心业务 * * 这里才是我们学习 Node 的精华部分:奥义之所在 * 封装异步 API */var fs = require(‘fs‘)var dbPath = ‘./db.json‘/** * 获取学生列表 * @param ?{Function} callback 回调函数 */exports.find = function (callback) { ?fs.readFile(dbPath, ‘utf8‘, function (err, data) { ???if (err) { ?????return callback(err) ???} ???callback(null, JSON.parse(data).students) ?})}/** * 根据 id 获取学生信息对象 * @param ?{Number} ??id ??????学生 id * @param ?{Function} callback 回调函数 */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) ?})}/** * 添加保存学生 * @param ?{Object} ??student ?学生对象 * @param ?{Function} callback 回调函数 */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) ???}) ?})}/** * 更新学生 */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 ???}) ???// 这种方式你就写死了,有 100 个难道就写 100 次吗? ???// 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) ???}) ?})}/** * 删除学生 */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) ???}) ?})}
student.js

2、项目搭建以及具体实现

第一步:搭建目录,用public文件夹来存放css img等静态文件,用views来存放页面

第二步:app.js作为整个项目的入口,先用express创建好服务器,

安装好express: npm install express

//引入expressvar express = require(‘express‘);//创建var app = new express();//请求访问app.get(‘/‘,function (req, res){ ?res.send(‘hello student‘)})//设置端口app.listen(3000, function () { ???console.log(‘server is running‘)})

第三步:配置开放静态资源 :项目中我们一般让public目录下的资源作为公共资源,可以给用户访问

//配置开放静态资源app.use(‘/public/‘, express.static(‘./public/‘))app.use(‘/node_moudles/‘, express.static(‘./node_moudles/‘))

第四步:读取数据文件将首页渲染出来,这里需要用到express-art-template包

安装:npm install express-art-template

配置如下:

//配置express-art-templateapp.engine(‘html‘, require(‘express-art-template‘))//使用模板来渲染app.get(‘/‘,function (req, res){//这里会默认到views文件下面去找index.html ?res.render(‘index.html‘, { ?????fruits: [ ?????‘苹果‘, ?????‘香蕉‘, ?????‘橘子‘ ?????] ?})})

第五步:读取数据,将数据渲染到页面中,先输出一下看看data里面的内容,

data中的内容如下:发现为一串十六进制数据,

用JSON.parse()函数可以将字符串转换为对象,如下图所示,现在我们可以拿到里面的对象了

第六步:需要进行路由设计,路由就相当于一张记录有所有路径信息的一张表,我们将所有要访问的路径存放在一张表中,利用node.js中的模块化思想,将每一个功能分块实现

(1) 路由表设计如下:

请求方法

请求路径

GET

POST

备注作用

GET

/ students

渲染首页

GET

GET

/students/new

/students/edit

点击 跳到一个新的添加页面,

跳到编辑页

POST

/students

Name age gender

点击Submit 按钮,跳到首页

post

/students/edit

Id

Name age gender

点击“编辑”,跳到编辑那个页面

GET

/students/delete

id

操作删除

(2)设计好路由表之后先将路由表的壳子搭好


//按照上面的表格配置好路由壳子
router.get(‘/‘, function (req, res) {});router.get(‘/students/new‘, function (req, res){});router.get(‘/students/edit‘, function (req, res){});router.post(‘/students‘, function (req, res) {});router.post(‘/students/edit‘, function (req, res) {});router.get(‘/students/delete‘, function(req, res) {});

(3)我们要在app.js中引用这个自定义的路由模块,所以需要在router.js中导出, 在app.js中引用

router.js中导出方法:

//最后还要导出这个路由module.exprots = router;

在app.js中引用

//引入路由var router = require(./router.js)//使用路由模块app.use(router)

将第五步中的请求/的一条路由放到router.js里面,测试一下是能请求成功的

第七步:上面的router.js中既有get 路由的功能,又有fs查询读取文件的功能,我们也可以用模块化 的思维,将router里面的增删改功能给抽取出来放到一个新的student.js模块中,让这个新的模块实现我们需要的功能

(1)同样先搭建好壳子,也需要导出,这里我们就用exports导出

//查找学生信息exports.find = function(){}//添加保存学生信息exports.save = function(){}//修改更新学生信息exports.updateById = function(){}//删除学生信息exports.deleteById = function(){}

(2)同样也需要在那边引用

//加入student模块var Student = require(‘./student.js‘)//调用Student.find()

第八步:查找实现,由于这个函数里面还用到了读取文件的操作,是异步的,所以不能用传统的函数调用的方式,要获取里面的数据需要用到回调函数来拿到数据

(1)在student.js中写查找方法

//可以先模拟调用写法//data=Student.find()由于函数中是异步的所以不能用传统的方式Student.find( function (data) { ?console.log(data)})
exports.find = function (callback) { ?fs.readFile(‘./data.json‘, ?function(err, data) { ????????????if (err) { ??????????????return callback(err); //如果文件读取错误,就结束让回调函数处理 ???????????} ????????//文件读取成功,第一个参数为null说明成功,这里需要将得到的二进制字符串转化为对象 ???????????callback(null, JSON.parse(data).students)})}

(2) router.js中调用如下:

//请求路径为/students的时候,调用find方法,并在页面中渲染数据router.get(‘/students‘, function (req, res) { ????????Student.find(function (err, students) { ???if(err) { ?????return res.status(500).send(‘Server err‘); ???} ?????res.render(‘index.html‘, { ?????fruits: [ ???????‘苹果‘, ???????‘香蕉‘, ???????‘橘子‘ ?????], ?????students: students ???}) })});

第九步:

(1)在student.js中写save添加方法,同样也可以先模拟调用再来写这个方法,添加的时候需要将要添加的对象传进去,然后在文件中添加传进去的对象,由于data文件是一个对象,还要将数组转化为对象

exports.save = function (student, callback ) { ????fs.readFile(‘./data.json‘, function (err, data) { ????if(err){ ????????return callback(err) ?//回调函数中如何处理错误,在这里我们不用关心 ????} ?????????//接受文件,这里得到的为数组 ????var students = JSON.parse(data).students ????student.id = students[students.length-1].id+1; ????//push向数组中添加新的 ????students.push(student); ????//执行完上面几步之后得到的是一个数组,但是在data中存入的是json格式的对象 ????var fileData = JSON.stringify({ ????????students: students ????}) ????//然后将文件写入data里面 ????fs.writeFile(‘./data.json‘, fileData, function (err){ ????????if(err){ ????????????callback(err); ????????} ????????callback(null); ????}) ?})}

(2)在router.js中调用:由于上面添加的过程提交的数据是以post方式提交,而express是不支持post提交的,所以要先安装一个body-parser包

安装:npm install body-parser

配置:

//安装好后引用包var bodyParse = require(‘body-parse‘);//配置app.use(bodyParse.urlencoded({ extentend: false}))app.use(bodyParse.json())

点击按钮跳到添加页面,然后点击提交按钮,将数据提交,并且页面重新跳到首页

router.get(‘/students/new‘, function (req, res){ ???res.render(‘new.html‘)});router.post(‘/students/new‘, function (req, res) {//先打印提交的内容 ???console.log(req.body); ???Student.save(req.body, function (err) { ?????if(err) { ????????return res.status(500).send(‘Server err‘); ?????}//重新跳会首页 ?????res.redirect(‘/students‘) ???})});

第十步:实现点击“编辑”跳到编辑页面

(1)这里需要通过id查询到点击的那条数据,并且在编辑页中渲染

//封装一个通过id请求的的函数exports.findById = function(id, callback) { ?fs.readFile(‘./data.json‘, ‘utf8‘, function (err, data) { ???if (err) { ?????return callback(err) ???} ???var students = JSON.parse(data).students ?//这个方法是es6提供的,当满足了item.id === parseInt(id),的时候会会返回整个对象 ???var ret = students.find(function (item) { ???????return item.id === parseInt(id); ???}) ???callback(null, ret);});}

(2)在router.js函数中get方式请求/students/edit

/这一次通过get到那个编辑页面router.get(‘/students/edit‘, function (req, res) { ?//调用得到的是保存之后的数据 ?//1.如何获取数据 ?//2.处理数据 ?//3.发送响应 ?//4.将数据再次写入data.json文件 ?Student.findById(req.query.id, function (err, student) { ???if (err) { ?????return res.status(500).send(‘Server err‘); ???} ???//console.log(student); ???res.render(‘edit.html‘,{ ?????student: student ???}) ?})});

(3)更新数据,需要以post方式提交数据到/students/edit,先在student

exports.find = function (callback){ ?fs.readFile(‘./data.json‘, function (err, data) { ????if(err){ ????????return callback(err) ?//回调函数中如何处理错误,在这里我们不用关心 ????} ????//这里的err=null说明请求成功 ????callback(null, JSON.parse(data).students); ?})}

(4)router.js中调用

router.post(‘/students/edit‘, function (req, res) { Student.updateById(req.body, function(err){ ??if (err){ ???return res.status(500).send(‘Server err‘); ??} ??res.redirect(‘/students‘) })});

第十一步:实现删除,删除的时候也要通过url地址拿到删除的id,然后查询到删除的对象

exports.deleteById = function (id, callback) { ????fs.readFile(‘./data.json‘,‘utf8‘, function (err, data) { ????if(err){ ????????return callback(err) ?//回调函数中如何处理错误,在这里我们不用关心 ????} ????//得到的是一个数组 ????var students = JSON.parse(data).students; ????var deleteId = students.findIndex(function (item) { ????????return item.id === parseInt(id); ????}) ????//做删除操作 ????students.splice(deleteId, 1); ????//删除之后吧数组转化为对象 ????var fileData = JSON.stringify({ ????????students:students ????}) ????fs.writeFile(‘./data.json‘, fileData, function(err){ ???????if(err) { ???????????return callback(err) ???????} ???????callback(null); ????}) });}

三、总结以及踩坑

1、做项目的时候可以将一些允许用户访问的静态资源文件放到一个public文件中,开放静态文件

2、要善于将项目中的功能分成模块化来处理

3、req.body拿到的是二进制或者十六进制数据,要对数据进行操作必须要用JSON.parse(data)转化为对象

4、将数组转化为对象用.

 var fileData = JSON.stringify({ ????????students:students ????})

node.js(小案例)_实现学生信息增删改

原文地址:https://www.cnblogs.com/xxm980617/p/10550179.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved