利用Express实现ADUS项目
使用Express可以快速地实现一个包含增删改查(CRUD)功能的Web项目,下面是一个基于Express实现的简单ADUS(添加、显示、更新、删除、搜索)项目
模块化思想
模块如何划分:
- 模块职责要单一
在使用Express实现一个CRUD项目时,通常可以将不同的功能模块划分为不同的路由和控制器,以实现代码的可读性和可维护性。在实现模块划分时,需要注意以下几点:
- 尽量保持模块功能单一。一个模块应该只包含一个相关的功能,以便于代码的维护和管理。
- 将路由和控制器分离。路由应该负责请求的转发和参数的解析,而控制器应该负责具体的业务逻辑。
- 使用中间件实现公共功能。比如身份验证、请求日志记录等功能可以使用中间件实现,避免代码重复。
- 将模块拆分为多个文件。当一个模块变得庞大时,可以将其拆分为多个文件,以便于代码的管理和维护。可以使用Node.js的模块系统来实现文件的拆分和组合。
javascript模块化:
- Node 中的 CommonJS
- 浏览器中的:
- AMD require.js
- CMD sea.js
- es6中增加了官方支持
起步
- 初始化
- 模板处理
路由设计
请求方法 | 请求路径 | get参数 | post参数 | 备注 |
GET | /students | 渲染首页 | ||
GET | /students/new | 渲染添加学生页面 | ||
POST | /students/new | name,age,gender,hobbies | 处理添加学生请求 | |
GET | /students/edit | id | 渲染编辑页面 | |
POST | /students/edit | id,name,age,gender,hobbies | 处理编辑请求 | |
GET | /students/delete | id | 处理删除请求 |
提取路由模块
router.js:
/** * router.js路由模块 * 职责: * 处理路由 * 根据不同的请求方法+请求路径设置具体的请求函数 * 模块职责要单一,我们划分模块的目的就是增强代码的可维护性,提升开发效率 */ var fs = require('fs'); // Express专门提供了一种更好的方式 // 专门用来提供路由的 var express = require('express'); // 1 创建一个路由容器 var router = express.Router(); // 2 把路由都挂载到路由容器中 router.get('/students', function(req, res) { // res.send('hello world'); // readFile的第二个参数是可选的,传入utf8就是告诉他把读取到的文件直接按照utf8编码,直接转成我们认识的字符 // 除了这样来转换,也可以通过data.toString()来转换 fs.readFile('./db.json', 'utf8', function(err, data) { if (err) { return res.status(500).send('Server error.') } // 读取到的文件数据是string类型的数据 // console.log(data); // 从文件中读取到的数据一定是字符串,所以一定要手动转换成对象 var students = JSON.parse(data).students; res.render('index.html', { // 读取文件数据 students:students }) }) }); router.get('/students/new',function(req,res){ res.render('new.html') }); 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;
app.js:
var router = require('./router'); // router(app); // 把路由容器挂载到app服务中 // 挂载路由 app.use(router);
设计操作数据的API文件模块
es6中的find和findIndex:
find接受一个方法作为参数,方法内部返回一个条件
find会便利所有的元素,执行你给定的带有条件返回值的函数
符合该条件的元素会作为find方法的返回值
如果遍历结束还没有符合该条件的元素,则返回undefined
/** * student.js * 数据操作文件模块 * 职责:操作文件中的数据,只处理数据,不关心业务 */ var fs = require('fs'); /** * 获取所有学生列表 * return [] */ exports.find = function(){ } /** * 获取添加保存学生 */ exports.save = function(){ } /** * 更新学生 */ exports.update = function(){ } /** * 删除学生 */ exports.delete = function(){ }
步骤
- 处理模板
- 配置静态开放资源
- 配置模板引擎
- 简单的路由,/studens渲染静态页出来
- 路由设计
- 提取路由模块
- 由于接下来的一系列业务操作都需要处理文件数据,所以我们需要封装Student.js'
- 先写好student.js文件结构
- 查询所有学生列别哦的API
- findById
- save
- updateById
- deleteById
- 实现具体功能
- 通过路由收到请求
- 接受请求中的参数(get,post)
- req.query
- req.body
- 调用数据操作API处理数据
- 根据操作结果给客户端发送请求
- 业务功能顺序
- 列表
- 添加
- 编辑
- 删除
子模板和模板的继承(模板引擎高级语法)【include,extend,block】
注意:
模板页:
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>模板页</title> <link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.css"/> {{ block 'head' }}{{ /block }} </head> <body> <!-- 通过include导入公共部分 --> {{include './header.html'}} <!-- 留一个位置 让别的内容去填充 --> {{ block 'content' }} <h1>默认内容</h1> {{ /block }} <!-- 通过include导入公共部分 --> {{include './footer.html'}} <!-- 公共样式 --> <script src="/node_modules/jquery/dist/jquery.js" ></script> <script src="/node_modules/bootstrap/dist/js/bootstrap.js" ></script> {{ block 'script' }}{{ /block }} </body> </html>
模板的继承:
header页面:
<div id=""> <h1>公共的头部</h1> </div>
footer页面:
<div id=""> <h1>公共的底部</h1> </div>
模板页的使用:
<!-- 继承(extend:延伸,扩展)模板也layout.html --> <!-- 把layout.html页面的内容都拿进来作为index.html页面的内容 --> {{extend './layout.html'}} <!-- 向模板页面填充新的数据 --> <!-- 填充后就会替换掉layout页面content中的数据 --> <!-- style样式方面的内容 --> {{ block 'head' }} <style type="text/css"> body{ background-color: skyblue; } </style> {{ /block }} {{ block 'content' }} <div id=""> <h1>Index页面的内容</h1> </div> {{ /block }} <!-- js部分的内容 --> {{ block 'script' }} <script type="text/javascript"> </script> {{ /block }}