【Node.js】学习node基础及其应用——学生管理系统(以文件的形式实现增删改查CRUD)

后台管理系统(增删改查)——CRUD by Express

下载运行

仓库连接(请各位老铁多多star): https://github.com/hcq29/Learning-Node.js.git

git clone https://github.com/hcq29/Learning-Node.js.git
cd Learning-Node.js
git checkout crud
node app.js

前期准备

安装配置

mkdir crud-express
cd crud-express/

npm init
Press ^C at any time to quit.
package name: (crud-express)
version: (1.0.0)
description: 增删改查crud-express
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to ..\笔记与代码\Learning-Node.js\Nodejs Code\18-CRUD-express\crud-express\package.json:

{
    
    
  "name": "crud-express",
  "version": "1.0.0",
  "description": "增删改查crud-express",
  "main": "index.js",
  "scripts": {
    
    
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Is this OK? (yes) y

npm install express --save
npm install art-template --save
npm install express-art-template --save
npm install express body-parser --save
npm install bootstrap --save
npm install nodemon --save

bootstrap网站实例: https://v3.bootcss.com/examples/dashboard/

改写index.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">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">
    <title>学生管理系统</title>
    <!-- Bootstrap core CSS -->
    <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="/public/css/main.css" rel="stylesheet">

  </head>
  <body>
      
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">学生管理系统</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav navbar-right">
            <li><a href="#">仪表板</a></li>
            <li><a href="#">设置</a></li>
            <li><a href="#">简况</a></li>
            <li><a href="#">帮助</a></li>
          </ul>
          <form class="navbar-form navbar-right">
            <input type="text" class="form-control" placeholder="搜索...">
          </form>
        </div>
      </div>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
          <ul class="nav nav-sidebar">
            <li class="active"><a href="#">概述 <span class="sr-only">(当前)</span></a></li>
            <li><a href="#">报告</a></li>
            <li><a href="#">分析</a></li>
            <li><a href="#">导出</a></li>
          </ul>
          <ul class="nav nav-sidebar">
            <li><a href="">导航栏</a></li>
            <li><a href="">Nav item again</a></li>
            <li><a href="">One more nav</a></li>
            <li><a href="">Another nav item</a></li>
            <li><a href="">More navigation</a></li>
          </ul>
          <ul class="nav nav-sidebar">
            <li><a href="">Nav item again</a></li>
            <li><a href="">One more nav</a></li>
            <li><a href="">Another nav item</a></li>
          </ul>
        </div>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
          <h2 class="sub-header">学生信息</h2>
          <button class="btn btn-success">添加</button>
          <div class="table-responsive">
            <table class="table table-striped">
              <thead>
                <tr>
                  <th>序号</th>
                  <th>姓名</th>
                  <th>性别</th>
                  <th>年龄</th>
                  <th>爱好</th>
                </tr>
              </thead>
              <tbody>
                {
   
   { 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}}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
    <script src="/node_modules/jquery/dist/jquery.js"></script>
    <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
    <script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
    <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
    <script src="/public/js/holder.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="/public/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>

路由设计

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

路由模块的提取

router.js路由模块

  • 处理路由
  • 根据不同的请求方法 + 请求路径设置具体的请求函数
/**
 * router.js
 */
// Express 提供了一个方式专门包装路由
const express = require('express');
// 创建一个路由容器
const router = express.Router();
const fs = require('fs');
const Student = require('./students');

// 把路由都挂在到 router 路由容器中
router.get('/students', (req, res) => {
    
    
    Student.find((err, students) => {
    
    
        //...
    })
})
router.get('/students/new', (req, res) => {
    
    
    res.render('new.html');
})
router.post('/students/new', (req, res) => {
    
    
    console.log(req.body)
    // ...
    // 1.获取表单数据
    // 2、处理
    //        将数据保存到students.json 文件中
    // 3、发送相应
    //     先读取文件,转成对象
    //     然后网对象中插入数据
    //     讲对象转为字符串
    //     将字符串再次写入文件
    Student.save(req.body, (err) => {
    
    
        if (err) return res.status(500).end('Server Error....');
        res.redirect('/students');
    })

})
router.get('/students/edit', (req, res) => {
    
    
    // 1、在客户端的列表页中处理链接问题(需要有 id 参数)
    // 2、获取要编辑的学生 id
    // 3、渲染编辑页面
    Student.findById(parseInt(req.query.id), (err, student)=>{
    
    
        if(err) return res.status(500).end('Server error....');
        res.render('edit.html',{
    
    
            student: student
        })
    })
})
router.post('/students/edit', (req, res) => {
    
    
    // 1、获取表单数据
    // 2、更新
    // 3、发送相应
    Student.update(req.body, (error)=>{
    
    
        if(error) return res.status(500).end('Server error....');
        res.redirect('/students');
    })
})
router.get('/students/delete', (req, res) => {
    
    
    Student.delete(parseInt(req.query.id), (err)=>{
    
    
        if(err) return res.status(500).end('Server error....');
        res.redirect('/students');
    })
})
// 把router导出
module.exports = router;

app.js入口模块

  • 启动服务
  • 做一些服务相关的配置
    • 模板引擎
    • body-parser 解析表单 post 请求体
    • 提供静态资源服务
  • 监听端口,启动服务
  • 挂载使用路由
/**
 * app.js
 */
const express = require('express');
const app = express();
const port = 3000;
const bodyParser = require('body-parser');
const router = require('./router');

app.engine('html', require('express-art-template'));

app.use(bodyParser.urlencoded({
    
    extended: false}));
app.use(bodyParser.json());

app.use('/public/', express.static('./public/'));
app.use('/node_modules/', express.static('./node_modules/'));
// 把路由容器挂载到 app 服务中
app.use(router);

app.listen(port, (error)=>{
    
    
    if(error) return console.log('服务器开启失败!');
    console.log('running in....' + port);
})

封装异步API

一般情况下,将函数作为参数就是为了获取函数内部的异步操作的结果,上层设计下层调用,这也是回调函数的作用所在。

function fn(callback){
    
    
	// var callback = function(data) { console.log(data)}
	setTimeout(function(){
    
    
		var data = 'hello';
		callback(data);
	},1000)
}
// 如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取
fn(function(data){
    
    
	console.log(data);
})

/**
 * students.js
 * 数据操作文件模块
 * 任务:操作文件中的数据,只处理数据,不管性业务
 * 
 */
const fs = require('fs');
const dbPath = './mock/db.json';

/**
 * 获取所有学生的列表
 */
exports.find = function (callback) {
    
    
    
}

/**
 * 查询对应学生 id 的所有信息
 */
exports.findById = function (id, callback) {
    
    
    
}

/**
 * 添加保存学生
 */
exports.save = function (student, callback) {
    
    
    // 1. 获取表单数据
	// 2. 处理
   	//- 将数据保存到db.json 文件中

	// 3. 发送相应
   //- 先读取文件,转成对象
   //- 然后网对象中插入数据
   //- 讲对象转为字符串
   //- 将字符串再次写入文件
}

/**
 * 更新学生
 */
exports.update = function (student, callback) {
    
    
    // 1、读取文件
    // 2、将文件中的字符串转为对象
    // 3、将 students 的 id 对应的 student 替换 
    // 4、重新写入文件
}

/**
 * 删除学生
 */
exports.delete = function (id, callback) {
    
    
    // 1、获取要删除学生的 id
    // 2、根据 id 执行删除操作
    // 3、根据操作结果进行发送相应结果
}

源代码请查看::https://github.com/hcq29/Learning-Node.js/tree/crud

具体效果:

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

猜你喜欢

转载自blog.csdn.net/weixin_42339197/article/details/104207474