zoukankan      html  css  js  c++  java
  • 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')
      })
    })
    

    来吧展示:

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

  • 相关阅读:
    计算机算法设计与分析之棋盘覆盖问题
    在uboot里面加入环境变量使用run来运行
    软件project师的属性与发展
    Oracle 表三种连接方式(sql优化)
    POJ 1700 cross river (数学模拟)
    八:Java之I/O
    为 Python Server Pages 和 Oracle 构建快速 Web 开发环境。
    WebBot
    WebBrowserProgramming
    Skulpt
  • 原文地址:https://www.cnblogs.com/Chinatsu/p/13823145.html
Copyright © 2011-2022 走看看