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

加油叭!!!


一、起步

项目结构

  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')
})
})

来吧展示:



Node.js学习笔记----day04之学生信息管理系统的更多相关文章

  1. Android(java)学习笔记195:学生信息管理系统案例(SQLite + ListView)

    1.首先说明一个知识点,通常我们显示布局文件xml都是如下: setContentView(R.layout.activity_main): 其实每一个xml布局文件就好像一个气球,我们可以使用Vie ...

  2. Android(java)学习笔记188:学生信息管理系统案例(SQLite + ListView)

    1.首先说明一个知识点,通常我们显示布局文件xml都是如下: setContentView(R.layout.activity_main): 其实每一个xml布局文件就好像一个气球,我们可以使用Vie ...

  3. Node.js学习笔记(3):NPM简明教程

    Node.js学习笔记(3):NPM简明教程 NPM常用操作 更新NPM版本 npm install npm -g -g,表示全局安装.我们可以指定更新版本,只需要在后面填上@版本号即可,也可以输入@ ...

  4. Node.js学习笔记(2):基本模块

    Node.js学习笔记(2):基本模块 模块 引入模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在No ...

  5. 一点感悟:《Node.js学习笔记》star数突破1000+

    写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...

  6. 系列文章--Node.js学习笔记系列

    Node.js学习笔记系列总索引 Nodejs学习笔记(一)--- 简介及安装Node.js开发环境 Nodejs学习笔记(二)--- 事件模块 Nodejs学习笔记(三)--- 模块 Nodejs学 ...

  7. Node.js学习笔记(1):Node.js快速开始

    Node.js学习笔记(1):Node.js快速开始 Node.js的安装 下载 官方网址:https://nodejs.org/en/ 说明: 在Windows上安装时务必选择全部组件,包括勾选Ad ...

  8. Node.js学习笔记(4):Yarn简明教程

    Node.js学习笔记(4):Yarn简明教程. 引入Yarn NPM是常用的包管理工具,现在我们引入是新一代的包管理工具Yarn.其具有快速.安全.可靠的特点. 安装方式 使用npm工具安装yarn ...

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

    一.前言 本节内容主要对小案例做一个总结: 1.如何开始搭建小项目 2.路由设计 3.模块应用 4.项目源码以及实现过程github地址: 项目演示如下: 二.主要内容 1.项目的关键性js源码: 项 ...

  10. Node.js学习笔记(一)

    1.回调函数 node是一个异步事件驱动的平台,所以在代码中我们经常需要使用回调函数. 例: setTimeout(function(){ console.log('callback is calle ...

随机推荐

  1. 详细了解JVM运行时内存

    详细了解JVM运行时内存 1.程序计数器 概念 程序计数器也叫作PC寄存器,是一块很小的内存区域,可以看做是当前线程执行的字节码的行号指示器.字节码的解释工作就是通过改变程序计数器里面的值来获得下一条 ...

  2. CodeTON Round 3 (C.差分维护,D.容斥原理)

    C. Complementary XOR 题目大意: 给你两个01串ab,问你是否可以通过一下两种操作在不超过n+5次的前提下将两个串都变为0,同时需要输出可以的操作方案 选择一个区间[l,r] 将串 ...

  3. pip 国内源 包管理

    配置国内源 linux配置 修改 ~/.pip/pip.conf 文件,如下,添加了源并修改了默认超时时间 [global] timeout = 3000 index-url = http://mir ...

  4. webpack -- element-ui 的按需引入

    简单说明原理: 使用babel-plugin-component实现按需引入.打包.将webpack配置成多入口,保证最终打包的目录结构符合babel-plugin-component插件的要求,实现 ...

  5. docker构建容器时 容器内使用代理

    build 容器时 使用代理 demo1 使用前 指定 env 使用后 记得 清空, 否则 会影响 使用容器 时的 网络 cat dockerfile --> FROM jenkins/jenk ...

  6. 【Devexpress】gridcontorl设置某个特定单元格不可编辑

    在gridcontorl中一般情况下我们使用的都是设置一列不可编辑 那么如何设置一个单元格不可编辑呢 在gridView1_ShowingEditor事件中可以实现.这个事件的意思是允许取消激活编辑器 ...

  7. Zabbix技术分享——使用Zabbix6.0监控业务日志

    企业日常IT运维过程中,常会碰到需要监控业务日志的情况,以下将介绍如何使用Zabbix6.0监控业务日志. 应用场景描述: 企业IT运维部门使用自建zabbix平台对公司某业务系统进行了监控.近段时间 ...

  8. Qwt开发笔记(一):Qwt简介、下载以及基础demo工程模板

    前言   QWT开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,本系列旨在系统解说并 ...

  9. log4j漏洞原理

    一.前置知识 1.JNDI接口 JNDI即Java Naming and Directory Interface(JAVA命名和目录接口),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发 ...

  10. 【CDH数仓】Day02:业务数仓搭建、Kerberos安全认证+Sentry权限管理、集群性能测试及资源管理、邮件报警、数据备份、节点添加删除、CDH的卸载

    五.业务数仓搭建 1.业务数据生成 建库建表gmall 需求:生成日期2019年2月10日数据.订单1000个.用户200个.商品sku300个.删除原始数据. CALL init_data('201 ...