其中主要封装的是 http
// 0. 安装
// 1. 引包
var express = require('express');
// 2. 创建服务器应用程序
// 也就是原来的 http.createServer();
var app = express();
// 公开指定目录
// 这样就能通过 /public/xx 的方式来访问 public 目录中的所有资源
// 在 Express中开放资源就是一个 API 的事
app.use('/public/', express.static('./public/'));
//模板引擎在 Express 中开放模板也是一个 API 的事
// 当服务器收到 get 请求 / 的时候,执行回调处理函数
// 使用 res.send 就不需要考虑编码问题
// 在 Express 中可以直接使用 req.query 来获取查询字符串参数
app.get('/', function(req,res){
res.send('hello express');
})
app.get('/about', function(req,res){
res.send('你好,我是Express!');
})
// 相当于 server.listen
app.listen(3000, function(){
console.log('app is runing at port 3000');
})
起步
安装
npm install express --save
使用
var express = require('express');
var app = express();
app.get('/', function(req,res){
res.send('hello world');
})
app.listen(3000, function(){
console.log('express app is runing...');
})
基本路由
- 请求方法
- 请求路径
请求处理函数
get
//当你以 get 方法请求/的时候,执行对应的处理函数
app.get('/', function(req,res){
res.send('hello world');
})
- post
//当你以 post 方法请求 / 的时候,执行对应的处理函数
app.post('/', function(req,res){
res.send('hello world');
})
静态服务
// 开放目录
app.use('/public/',express.static('./public/'));
// 当省略第一个参数的时候,则 url 可以省略 /public 来访问
app.use(express.static('./public/'));
// a 相当于 public 的别名,通过 /a/文件名 来访问 public 目录下的文件
app.use('/a/',express.static('./public/'));
使用 art-template 模板引擎
- art-template官方中文文档
- 在 node中,有很多第三方模板引擎都可以使用,不是只有
art-template
- 还有ejs,jade(pug),handlebars,nunjucks
安装
c npm install --save art-template
c npm install --save express-art-template
// 同时安装两个时用空格隔开
c npm i --save art-template express-art-template
配置
// 表示当渲染 .art 文件时,使用 art-template 模板引擎,使用 .art 只是为了更好辨别
// express-art-template 是专门用来在 express 中使用的 art-template
// 因为 express-art-template 依赖了 art-template ,所以不加载也必须安装
// app.engine('art', require('express-art-template'));
app.engine('html', require('express-art-template'))
使用
app.get('/',function(req,res){
// 第一个参数不能写路径,默认会去 views 目录找 index.html
res.render('admin/index.html',{
title:'hello world'
});
})
如果想要修改默认的 views 视图渲染存储目录,可以:
// 第一个参数 views千万不要写错
app.set('views', 默认路径);
日期格式化
https://blog.csdn.net/qincidong/article/details/82252298 https://www.cnblogs.com/HJ412/p/11495588.html
获取表单请求体数据
获取 GET 请求数据
Express 内置了一个 api,可以直接通过 req.query
来获取数据
// 通过 requery 方法获取用户输入的数据
// req.query 只能拿到 get 请求的数据
var comment = req.query;
获取POST请求数据
在 Express中 没有内置获取表单 post 请求体的 api,这里我们需要使用中间件 body-parser
来获取数据。
- 安装
cnpm install --save body-parser
- 配置
http://expressjs.com/en/resources/middleware/body-parser.html
配置解析表单 POST 请求体插件(注意:一定要在 app.use(router) 之前 )
var express = require('express')
// 引包
var bodyParser = require('body-parser')
var app = express()
// 配置 body-parser
// 只要加入这个配置,则在 req 请求对象上会多出来一个属性:body
// 也就是说可以直接通过 req.body 来获取表单 post 请求体数据
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
- 使用
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
// 可以通过 req.body 来获取表单请求数据
res.end(JSON.stringify(req.body, null, 2))
})
session
安装
cnpm i express-session --save
配置
// 该插件会为 req 请求对象添加一个成员:req.session 默认是一个对象
// 这是最简单的配置方式
// Session 是基于 Cookie 实现的
app.use(session({
// secret 配置加密字符串,他会在原有的基础上和字符串拼接起来去加密
// 目的是为了增加安全性,防止客户端恶意伪造
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,// 无论是否适用 Session,都默认直接分配一把钥匙
}))
使用
//添加 Session 数据
//session 就是一个对象
req.session.foo = 'bar';
//获取 session 数据
req.session.foo
//删除 session 数据
req.session.foo = null;
delete req.session.foo
提示:默认 Session 数据是内存储数据,服务器一旦重启就会丢失,真正的生产环境会把 Session 进行持久化存储。
CRUD 案例
实现步骤
- 处理模板
- 配置静态开放资源
- 配置模板引擎
- 简单的路由,/studens渲染静态页出来
- 路由设计
- 提取路由模块
- 由于接下来的一系列业务操作都需要处理文件数据,所以我们需要封装Student.js’
- 先写好 student.js 文件结构
- 查询所有学生列表的API
- findById
- save
- updateById
- deleteById
- 实现具体功能
- 通过路由收到请求
- 接受请求中的参数(get,post)
- req.query
- req.body
- 调用数据操作API处理数据
- 根据操作结果给客户端发送响应
- 业务功能顺序
- 列表
- 添加
- 编辑
- 删除
模块化
模块如何划分:
- 模块职责要单一
javascript 模块化:
- Node 中的 CommonJS
- 浏览器中的:
- AMD
- CMD
- 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')
var Students = require('./students')
// Express 提供了一种专门用来 包装 路由的 方式
var express = require('express')
// 1 .创建一个路由容器
var router = express.Router()
// 2. 把路由都挂载到 router 路由容器中
/**
* 渲染学生列表页面
*/
router.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.')
}
// 读取到的文件数据是 string 类型的数据
// 需要转换成对象
var students = JSON.parse(data).students;
res.render('index.html', {
students:students
})
})
});
/**
* 渲染学生添加页面
*/
router.get('/students/new',function(req,res){
res.render('new.html')
});
/**
* 处理添加学生
*/
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;
app.js:
/**
* app.js 入口模块
* 职责:
* 创建服务
* 做一些服务相关配置
* 模板引擎
* body-parser 解析表单 Post 请求体
* 提供静态资源服务
* 挂载路由
* 监听端口启动服务
*/
var express = require('express')
var router = require('./router .js ')
var bodyParser = require('body-parser')
var app = express()
// 开放目录
app.use(' / node_modules / ', exp r ess.static('./n o de_mod u les/'))
app.use('/public/', express.s t atic('./public/'))
// 配置模板引擎和 body-parser 一定要在 app.user(router) 挂载路由之前
app.engine('html', r equire ( 'express-art-template'))
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// router(app)
// 把路由容器挂载到 app 服务中
app.use(router)
app.listen(1314, function (req, res) {
console.log('running 1314...')
})
设计操作数据的 API 文件模块
es6中的 find 和findIndex:
find 接受一个方法作为参数,方法内部返回一个条件
find 会便利所有的元素,执行你给定的带有条件返回值的函数
符合该条件的元素会作为 find 方法的返回值
如果遍历结束还没有符合该条件的元素,则返回 undefined
/**
* student.js
* 数据操作文件模块
* 职责:操作文件中的数据,只处理数据,不关心业务
*/
var fs = require('fs')
/**
* 获取所有学生列表
* return []
*/
exports.find = function(){
}
/**
* 根据 id 获取学生信息对象(单个学生)
*/
exports.findById = function (id, callback) {
}
/**
* 获取添加保存学生
*/
exports.save = function(){
}
/**
* 更新学生
*/
exports.updat aById = function(){
}
/**
* 删除学生
*/
exports.delete ById = function(){
}
子模板和模板的继承(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 }}