做这个项目一方面是熟悉express,一方面也是对整个小项目流程有个整体的了解,记录一下,有页面,有渲染,也是知识的整合总结。
首先 :创建一个文件夹,里面是我们用到的各种项目文件。crud-express
然后按照之前得知识:
1.建包的依赖项 npm init -y
2.安装express npm i -S express(express 包就放在了工程目录下的 node_modules 目录中)
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)
})
})
}
3.新建一些文件夹,public(css,js.img) ,views(index.html),app.js(整个程序入口函数)
4.安装模板引擎 npm install --save art-templa npm install --save express-art-template (app.engine('html',require('express-art-template')))
5.下载bootstrap模板 ,服务端先不管页面。更改下引入路径 <link href="/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
6.从文件中读取数据,新建db.json 文件,进行文件的改写,然后进行模板的渲染,<tbody>
{{each students}}
<tr>
<td>{{ $value.id }}</td>
<td>{{ $value.name }}</td>
<td>{{ $value.gender }}</td>
<td>{{ $value.age }}</td>
<td>{{ $value.hobby }}</td>
</tr>
{{ /each}}
7.从db.json把文件读出来:引入fs,然后 fs.readFile('./db.json', 'utf8',function(err,data){
if (err){
return res.status(500),send('Sever error')
}
res.render('index.html', {
//从文件从读取到的文件一定是字符串,所以从这里一定要手动转成对象
students:JSON.parse(data).students
})
8.为了不同请求不同相应,需要设计路由,路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码。
路由设计
| 请求方法 | 请求路径 | 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 | | 处理删除请求 |
| | | | | |
9.router.js 中是各种请求的代码。app.js 创建服务,基本配置,启动监听。两个文件怎么关联,express 提供了
// Express 提供了一种更好的方式
// 专门用来包装路由的
var express = require('express')
// 1. 创建一个路由容器
var router = express.Router()
// 2. 把路由都挂载到 router 路由容器中
router.get('/students',function (req,res) {
})
//3.把router 导出
module.exports = router
4.//把路由容器加载到app服务中
app.use(router)
app.js作用:* app.js 入门模块
* 职责:
* 创建服务
* 做一些服务相关配置
* 模板引擎
* body-parser 解析表单 post 请求体
* 提供静态资源服务
* 挂载路由
* 监听端口启动服务
*/
* router.js 路由模块
* 职责:
* 处理路由
* 根据不同的请求方法+请求路径设置具体的请求处理函数
* 模块职责要单一,不要乱写
* 我们划分模块的目的就是为了增强项目代码的可维护性
* 提升开发效率
*/
10.填表单提交数据 1.获取表单数据 ,2,处理(将数据保存到db.json 文件中用以持久化) 3,发送响应 在express中没有能获取数据的API,所以得自己配置插件,获取表单数据post 第一步 ,先安装:npm install --save body-parser, 然后再app.js 引入两个核心api var bodyParser = require('body-parser')
// 配置模板引擎和 body-parser 一定要在 app.use(router) 挂载路由之前
// parse application/x-www-form-urlencodedapp.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
文件中保存数据 ,先读取出来,转对象,然后往对象push数据,然后对象转为字符串,然后再把字符串写入文件
11./**
* student.js
* 数据操作文件模块
* 职责:操作文件中的数据,只处理数据,不关心业务
*
* 这里才是我们学习 Node 的精华部分:奥义之所在
* 封装异步 API
*/
//获取所有学生列表
exports.find = function() {
}
//添加保存学生
exports.save = function() {
}
//更新学生
exports.update = function() {
}
//删除学生
exports.delete = function() {
}
设计操作文件的api
遇到一个很大的问题,一直数据提交不进主页面,说数据未定义,代码虽然正确,但有的时候忘了保存。
//更新学生
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)
// 添加 id ,唯一不重复
// 你要修改谁,就需要把谁找出来
// EcmaScript 6 中的一个数组方法:find
// 需要接收一个函数作为参数
// 当某个遍历项符合 item.id === student.id 条件的时候,find 会终止遍历,同时返回遍历项
var stu = students.find(function(item){
return item.id === student.id
})
// 遍历拷贝对象
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.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中在渲染
第一大步,把对象找出来,完成渲染编辑学生页面 在index.html中添加 编辑 删除,$value.id 注意是$ ,不是&
// 1. 在客户端的列表页中处理链接问题(需要有 id 参数)
// 2. 获取要编辑的学生 id
// 3. 渲染编辑页面
// 根据 id 把学生信息查出来
// 使用模板引擎渲染页面 /**
* 根据 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)
})
} * 渲染添加学生页面
*/
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
})
})
})
第二部分 编辑处理学生 路由表中没有ID 要在 edit.html中 添加hidden ID
<input type="hidden" name="id" value="{{ student.id }}">
然更新,渲染//更新学生
exports.updateById = function(student,callback){
fs.readFile(dbPath, 'utf8', function (err, data) {
if (err) {
return callback(err)
}
var students = JSON.parse(data).students
// 注意:这里记得把 id 统一转换为数字类型 防止字符串id 把数字id tihuan
student.id = parseInt(student.id)
// 添加 id ,唯一不重复
// 你要修改谁,就需要把谁找出来
// EcmaScript 6 中的一个数组方法:find
// 需要接收一个函数作为参数
// 当某个遍历项符合 item.id === student.id 条件的时候,find 会终止遍历,同时返回遍历项
var stu = students.find(function(item){
return item.id === student.id
})
// 遍历拷贝对象
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)
})
})
}
//处理编辑学生
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
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) {
Student.deleteById(req.query.id, function (err) {
if (err) {
return res.status(500).send('Server error.')
}
res.redirect('/students')
})
})
总结:
![](https://i-blog.csdnimg.cn/blog_migrate/fc9788a13ba884034dd1b2aeaa4f9d4d.png)