node.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-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.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) {

//   })
// }

功能实现模块

/**
 * 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

//引入express
var 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-template
app.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
     })

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

时间: 2024-10-09 10:27:03

node.js(小案例)_实现学生信息增删改的相关文章

Java学生信息增删改查(并没用数据库)

一个泛型的应用,Java版本增删改查,写的简陋,望批评指正 2016-07-02 很久前写的一个程序了.拿出来存一下,不是为了展示啥,自己用的时候还可以看看.写的很粗糙. 1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileNotFoundException; 4 import java.io.FileReader; 5 import java.io.IOException; 6 import

小草的Trouble学生信息管理系统

小草最近上课学C++,在图书馆纠结了好久,决定做这个小东西,没想到遇到了好多困难,好吧,功夫不负有心人,小草也在敲代码中提高了不少. 小草硬是学了好几天,才搞完这个东西,也算是了结了小草的一个心结. 小草的Trouble学生信息管理系统写得不咋样,就是一个学习C++的笔记吧. 1.类. 2.继承与派生. #include <stdio.h> #include <iostream> #include <stdlib.h> #include <algorithm>

Node+Express+node-mysql 实战于演习 全套mysql(增删改查)

最近这段时间研究Node感觉不错,自己做了一个增删改查,虽然有些简陋,但是思想是想通的,其实所有项目都是增删改查,有助于初学者快速掌握Node 首先 本实例展示的是基于Node+Express+node-mysql快速搭建的一套增删改查,视图模板是jade,基本上都是现在能用的到的技术,市面上的实例也特别少,有用的又不新,所以自己写一个 基本工作 首先我们准备一些基本的,因为我是用mysql麻烦可以自己装一下mysql,去官网可以下各种操作系统的安装包. 实例就一张表,下面是这张表的建表语句 S

python学习之-员信息增删改查

python学习之-成员信息增删改查 主要实现了成员信息的增加,修改,查询,和删除功能,写着玩玩,在写的过程中,遇到的问题,旧新成员信息数据的合并,手机号和邮箱的验证, #!/usr/bin/env python# coding=utf8#author:[email protected] import os, sys, time,jsonimport re member_dict = \ {}member_name_list = []member_list = []def handler_mem

项目:员工信息增删改查程序

现要求写一个简单的员工信息增删改查程序,需求如下: 当然此表你在文件存储时可以这样表示 1,Alex Li,22,13651054608,IT,2013-04-01 2,Jack Wang,28,13451024608,HR,2015-01-07 3,Rain Wang,21,13451054608,IT,2017-04-01 4,Mack Qiao,44,15653354208,Sales,2016-02-01 5,Rachel Chen,23,13351024606,IT,2013-03-1

实现学校信息增删改查-第一节添加学校名称

SSM框架实现学校信息增删改查-第一节添加学校名称 大家好!第一次写文 语句可能有些生涩,看到我不足的地方可以给我留言~ 好了,开始第一节,一个简单的添加学校名称功能~ 可以先看一下前端html代码,运行程序看一些界面效果 超级简易的一个添加页面,首先我们要知道添加是根据学校id添加信息的,请看代码哦 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

JS小案例分析

a.微博输入删除小案例 <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } ul { list-style: none; } .box { width: 600px; margin: 100px auto; b

将xml文件作为一个小的数据库,进行学生的增删改查

1.xml文件: 1 <?xml version="1.0" encoding="UTF-8"?><Students> 2 <student id="2"> 3 <name>ttt</name> 4 <age>44</age> 5 </student> 6 <student id="3"> 7 <name>l

python练习——moudule02——员工信息增删改查

#作业名称:员工信息的增删改查 #作业需求: 1.可进行模糊查询,语法至少支持下面3种: select name,age from staff_table where age > 22 select * from staff_table where dept = "IT" select * from staff_table where enroll_date like "2013" 查到的信息,打印后,最后面还要显示查到的条数 2.可创建新员工纪录,以phon