Express 是一个基于 Node.js 平台,快速、开放、极简的 web 开发框架。
原生的 http 模块在某些方面表现不足以应对我们的开发需求,所以我们就需要使用框架来加快我们的开发效率,框架的目的就是提高效率,让我们的代码更统一。

  • 丰富的 API 支持,强大而灵活的中间件特性
  • Express 不对 Node.js 已有的特性进行二次抽象,只是在它之上扩展了 Web 应用所需的基本功能
    • 内部使用还是 http 模块
  • 有很多流行框架基于 Express

安装

  1. npm install --save express

使用

express 提供一些函数

  • app.listen ```javascript const http = require(‘http’);

const express = require(‘express’);

const app = express(); // 返回一个 requestListener 处理器

app.listen(3000); // 相当于 // const server = hhtp.createServer(app); // server.listen(3000);

  1. <a name="KJEZC"></a>
  2. # 中间件
  3. 通过中间件对整个处理请求函数增加对应的方法,即把不同对应处理的函数分配到各个中间件中。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1753568/1617242127111-78173a68-10ee-40af-a270-f51acbcfcf9d.png#height=521&id=TOHYJ&margin=%5Bobject%20Object%5D&name=image.png&originHeight=521&originWidth=296&originalType=binary&ratio=1&size=260260&status=done&style=none&width=296)
  4. <a name="CqQOs"></a>
  5. ## 中间件工作原理
  6. app.use([path,] callback [, callback...])
  7. 中间件的回调函数
  8. - 一般响应回调为三个以下或以下
  9. - function(req, res)
  10. - function(req, res, next)
  11. - 错误处理为四个参数 function(err, req, res, next)
  12. err 为错误信息<br />req 请求对象,继承自 http.IncomingMessage<br />res 响应对象,继承自 http.ServerResponse
  13. - res.send express 的响应函数 res 参数除了可以原生使用 write 等 http 原生写响应,也可以使用 send 方法简化响应体
  14. - res.redirect express 提供用于重定向
  15. ```javascript
  16. res.redirect('/');
  17. // 相当于
  18. res.statusCode = 302;
  19. res.setHeader('Location', '/');
  • res.sendFile 返回响应文件
  • res.status() 指定发送状态码

    1. // 如 404 页面
    2. app.use((req, res, next) => {
    3. res.status(404).send('<h1>页面走丢了!</h1>');
    4. });

    next

  • next() 往后匹配下一个中间件

  • next(‘route’) 往后匹配当前中间件堆栈中的下一个
  • next(x) x为任何除字符串 'route' 外,会视当前请求错误,将路过所有剩余无错误处理路由和中间件函数

  • app.use 使用中间件处理各种请求

  • app.post

  • app.get
  • app.delete

这些都是一个内置的中间件

这些要完全匹配path

  1. app.use((req, res, next) => {
  2. console.log('在中间件中');
  3. next(); // 往下流
  4. });

多个中间件函数

  1. app.get('/', (req, res, next) => {}, (req, res, next) => {});

中间件堆栈

  1. const cb1 = (req, res, next) => {};
  2. const cb2 = (req, res, next) => {};
  3. app.get('/', [cb1, cb2]);

中间件链式

  1. app.get('/', (req, res) => {
  2. res.send(`get`)
  3. }).post('/', (req, res) => {
  4. res.send(`post`)
  5. }).put('/', (req, res) => {
  6. res.send(`put`)
  7. }).delete('/', (req, res) => {
  8. res.send(`delete`)
  9. })

中间件 path 过滤响应与参数

使用 path 控制响应的内容,支持 字符串或正则,可以使用 :params 设置参数

  1. app.get('/', (req, res, next) => { // 在没有匹配到的默认响应
  2. console.log('这个中间件永远都会执行');
  3. next();
  4. });
  5. app.get('/add-product', (req, res, next) => { // 在 path 为 '/' 之前增加
  6. res.send('<h1>添加产品页面</h1>');
  7. });
  8. app.get('/', (req, res, next) => { // 在没有匹配到的默认响应
  9. res.send('<h1>你好,Express!</h1>');
  10. });
  11. app.get('/:id', (req, res, next) => {
  12. console.log(req.params.id);
  13. });
  14. // path 字符串
  15. // 可以用 ? + {} 等正则量词
  16. app.get('/a(bc)?d', (req, res, next) => {
  17. });
  18. app.get('/ab+', (req, res, next) => {
  19. });
  20. app.get('/a{1,4}', (req, res, next) => {
  21. });
  22. // 可以使用 . - 来分隔参数
  23. app.get('/:id1.:id2', (req, res, next) => {
  24. console.log(req.params.id1);
  25. console.log(req.params.id2);
  26. });
  27. // 可以使用 . - 来分隔参数
  28. app.get('/:id1-:id2', (req, res, next) => {
  29. console.log(req.params.id1);
  30. console.log(req.params.id2);
  31. });
  32. // 可以使用 . - 来分隔参数
  33. app.get('/:id1-:id2', (req, res, next) => {
  34. console.log(req.params.id1);
  35. console.log(req.params.id2);
  36. });
  37. // 可以用 (正则) 为参数指定类型,注意字符串要用 \ 转意
  38. app.get('/:id1(\\d+), (req, res, next) => {
  39. console.log(req.params.id1);
  40. console.log(req.params.id2);
  41. });
  42. // 使用正则匹配
  43. app.get(/a/) , (req, res, next) => {
  44. });
  45. app.get(/^bad.*fly$/) , (req, res, next) => {
  46. });

内置中间件

express.json()
express.urlencoded()

  1. app.use(express.json()); // 处理请求体 raw 为 json 的参数
  2. app.use(express.urlencoded()); // 处理请求体 x-www-form-urlencoded 的参数
  3. app.get('/', function(req, res, next) {
  4. console.log(req.body);
  5. })

外置中间件

body-parser
用于解析body请求体的解析器

  1. npm install --save body-parser

bodyParser.urlencoded() 返回一个中间件函数

  1. const bodyParser = require('body-parser');
  2. app.use(bodyParaser.urlencoded({extended:false})); // 不去处理非标准的请求

:::info express v4 版本其实已经对 body-parser 相关的封装到 express 内置中间件,所以现在也很少使用 body-parser :::

cookie-parser 解析 cookie 数据
cors 跨域
compression 压缩 HTTP 响应
morgan 请求日志

其他中间件可以访问:

路由

使用express.Router() 可以分拆业务逻辑, 返回中间件函数
admin.js

  1. const express = require('express');
  2. const router = express.Router();
  3. router.get('/add-product', (req, res, next) => {
  4. res.send('<form action="/product" method="POST"><input type="text" name="message" /><button="submit">发送</button></form>');
  5. });
  6. router.post('/product', (req,res, next) => {
  7. res.redirect('/');
  8. });
  9. module.exporets = router;

在app.js中, 路径过滤

  1. const adminRoutes = require('./routes/admin');
  2. // 在path中加入'/admin'进行路径过滤,即访问时要/admin/add-product才能访问到
  3. app.use('/admin', adminRoutes);

静态文件提供

express.static()

  1. app.use(express.static('./public'));

模板引擎

image.png
image.png

  1. npm install --save ejs pug express-handlebars

配置模板引擎

  1. app.set('view engine', 'pug'); // 配置要使用的引擎
  2. app.set('view', './view'); // 配置模板位置

使用模板

  1. route.get('/', (req, res, next) => {
  2. res.render('模板文件名', {data:'住模板注入数据'});
  3. }


ejs

pug

handlebars

  1. const expressHbs = require('express-handles');
  2. app.engine('handlebars', expressHbs({layoutDir: 'views/layouts', defaultLayout: 'main-layout', extname: 'hbs'})); // 要先注册一个模板引擎