使用前面的案例定义模块化简单案例
一、路由设计
请求方法 | 请求路径 | 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 | 处理删除请求 | |
二、路由模块
express.Router()
路由模块,使用express框架更方便一些
处理路由
根据不同的请求方法+请求路径设置具体的请求处理函数、
router.js:
- 创建一个路由容器
var fs = require('fs')//读取文件模块
var Student = require('./student')//Student 模块下面定义
var router = express.Router()// 配置路由器
- 把路由都挂载到 router 路由容器中
router.get()
router.post()
/*
* 渲染学生列表页面
*/
router.get('/students', function (req, res) {
//Student模块定义的查询
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) {
//渲染new.html
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')
})
})
- 把 router 导出
module.exports = router
//不要使用下面这种方式还要 .router 会麻烦一些。 上面是直接导出
exports.router = 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) {
})
}
三、应用路由模块
创建服务 做一些服务相关配置, 提供静态资源服务 。监听端口启动服务 .挂载路由
app.js :
- 导入模块,应用express
var express = require('express')//express 插件
var router = require('./router') //导入定义的路由模块
var bodyParser = require('body-parser') //post请求数据格式化插件
//应用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'))
// 配置模板引擎和 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...')
})
- 模块导出
//导出模块,给上面原生方法封装使用的基础配置模块。 express中用不到了
module.exports = app
四、student数据模块
这里只做异步操作示例,后期就是数据库操作模块。还可以细分每一个功能的模块
student.js:
/**
* 封装异步 API
*/
var fs = require('fs')
var dbPath = {
"students": [
{
"id": 1,
"name": "张s",
"gender": "0",
"age": "24",
"hobbies": "吃饭、打豆豆"
},
{
"id": 2,
"name": "张f",
"gender": "0",
"age": "23",
"hobbies": "吃饭、睡觉"
},
{
"id": 3,
"name": "张3",
"gender": "0",
"age": "21",
"hobbies": "睡觉、打豆豆"
},
{
"id": 4,
"name": "张三三",
"gender": "0",
"age": "22",
"hobbies": "吃饭、睡觉、打豆豆"
}
]
}
/**
* 获取学生列表
* @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) {
//utf8编码自动是字符串不需要tostring
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)
})
})
}