http://expressjs.com

其中主要封装的是 http

  1. // 0. 安装
  2. // 1. 引包
  3. var express = require('express');
  4. // 2. 创建服务器应用程序
  5. // 也就是原来的 http.createServer();
  6. var app = express();
  7. // 公开指定目录
  8. // 这样就能通过 /public/xx 的方式来访问 public 目录中的所有资源
  9. // 在 Express中开放资源就是一个 API 的事
  10. app.use('/public/', express.static('./public/'));
  11. //模板引擎在 Express 中开放模板也是一个 API 的事
  12. // 当服务器收到 get 请求 / 的时候,执行回调处理函数
  13. // 使用 res.send 就不需要考虑编码问题
  14. // 在 Express 中可以直接使用 req.query 来获取查询字符串参数
  15. app.get('/', function(req,res){
  16. res.send('hello express');
  17. })
  18. app.get('/about', function(req,res){
  19. res.send('你好,我是Express!');
  20. })
  21. // 相当于 server.listen
  22. app.listen(3000, function(){
  23. console.log('app is runing at port 3000');
  24. })

起步

安装

  1. 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

参考文档: https://github.com/expressjs/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 }}