Node.js - express

150 阅读4分钟

express 介绍

express 是一个基于node.js平台的极简、灵活的web应用开发框架,官方网站:www.expressjs.com.cn/
简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发web应用(HTTP服务)

二、express使用

2.1 express 下载

express 本身是一个 npm 包,所以可以通过npm安装

2.2 express初体验

1、创建js文件,键入代码:

// 1、 导入 express
const express = require('express');

// 2、创建应用对象
const app = express();

// 3、创建路由
app.get('/home', (req, res) => {
    res.end('express');
});

// 4、监听端口
app.listen(8080, () => {
    console.log('启动');
});

2、命令行执行

nodemon xxx.js
或
node xxx.js

3、浏览器输入

http://127.0.0.1:8080/home

image.png

三、express路由

3.1 什么是路由

官方定义:路由确定了应用程序如何响应客户端对特定端点的请求

3.2 路由的使用

一个路由的组成由 请求方法,路径和回调函数组成 express 中提供了一系列的方法,可以很方便的使用路由,格式为:

app.<method>(path, callback)
// get 路由
app.get('/home', (req, res) => {
    res.end('home');
});
// 首页
app.get('/', (req, res) => {
    res.end('/');
});
// post
app.post('/login', (req, res) => {
    res.end('login');
});
// 匹配所有方法
app.all('/test', (req, res) => {
    res.end('test');
});
// 处理404响应
app.all('*', (req, res) => {
    res.end('*');
});

3.3 获取请求参数

express框架封装了一些API来方便获取请求报文中的数据,并且兼容原生HTTP模块的获取方式

app.get('/request', (req, res) => {
    // 原生操作 与原生http获取方式兼容
    console.log(req.method);
    console.log(req.httpVersion);
    console.log(req.url);
    console.log(req.headers);

    // express 独有的获取报文的方式
    // 路径
    console.log(req.path);
    // 获取查询字符串
    console.log(req.query);
    // 获取IP
    console.log(req.ip);
    // 获取请求头
    console.log(req.get('host'));
    res.end('请求报文的获取');
})

3.4 获取路由参数

路由参数指的是 URL 路径中的参数(数据)

app.get('/:id.html', (req, res)=>{
    // 获取URL路由参数
    console.log(req.params.id);
    res.send(`商品详情,商品ID为${req.params.id}`)
})

四、express 响应设置

express 框架封装了一些API来方便给客户端响应数据,并且兼容原生HTTP模块的获取方式

app.get('/response', (req, res) => {
    // 设置响应 与原生http获取方式兼容
    response.statusCode = 404
    response.statusMessage = '404'
    response.setHeader('Accept-Language', 'zh-CN')
    response.write('响应体')
    res.end('end');

    // // express 响应方法
    // // 设置响应状态码
    res.status(404);
    // 设置响应头
    res.set('aaa', 'bbb');
    // 设置响应体
    res.send('中文不乱码');
    // 可以连贯操作
    res.status(404).set('aaa', 'bbb').send('可以这样');

    // 其他响应
    // 跳转响应  重定向
    res.redirect('https://www.baidu.com/');
    // 下载响应
    res.download(`${__dirname}/package.json`);
    // JSON响应
    res.json({
        "name": "express",
        "version": "1.0.0",
    })
    // 响应文件内容
    res.sendFile(`${__dirname}/index.html`)
})

五、express 中间件

5.1 什么是中间件

中间件 (Middlewace) 本质是一个回调函数 中间件函数可以像路由回调一样访问请求对象 (request) ,响应对象 (response)

5.2 中间件的作用

中间件的作用就是使用函数封装公共操作,简化代码

5.3 中间件的类型

  • 全局中间件
  • 路由中间件

5.3.1 定义全局中间件

每一个请求到达服务器之后都会执行全局中间件函数 声明中间件函数

let recordMiddleware = function (req, res, next) {
    // 实现功能代码
    // ....
    // 执行next函数(如果希望执行完中间函数之后,仍然继续执行路由中的回调函数,必须调用next()
    next();
}
// 全局中间件  需求:记录每个访问的URL和IP信息
function recordMiddleware(req, res, next) {
    // 获取URL IP
    let { url, ip } = req;
    // 将信息存在 access.log
    fs.appendFileSync(path.resolve(__dirname, 'access.log'), `${url} ${ip}\r\n`)
    next();
};
// 使用中间件函数
// 全局中间件使用 app.use
app.use(recordMiddleware);
// 可以使用app.use连续多个定义中间件
app.use(fun1)
app.use(fun2)
app.use(fun3)
...

5.3.2 定义路由中间件

// 路由中间件 
/**
 * 针对 /admin /setting 的请求,要求URL携带 code=500 参数,如未携带提示 暗号错误
 */

// 声明中间件
function checkCodeMiddleware(req, res, next) {
    // 判断 URL 中code参数是否等于500
    if (req.query.code === '500') {
        next()
    }else{
        res.send('暗号错误')
    }
}
// 路由中间件在受约束的路由中
app.get('/admin', checkCodeMiddleware, (req, res) => {
    res.send('后台首页')
})
app.get('/setting', checkCodeMiddleware, (req, res) => {
    res.send('设置页面')
})
// 多个路由中间件
app.get('.xxx', fun1, fun2, ..., (req, res) => {})

5.4 静态资源中间件

express 内置处理静态资源的中间件

// 静态资源中间件设置 将当前文件夹下的public目录作为网站的根目录
// 当前public目录下都是一些静态资源,html css js img 等
app.use(express.static(`${__dirname}/public`))
app.get('/index.html', (req, res) => {
    res.send('首页')
})

注意事项

  • index.html 文件为默认打开的资源
  • 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
  • 路由响应动态资源,静态资源中间件响应静态资源

5.5 获取请求体数据 body-parser

express 可以使用 body-parser 包处理请求体 第一步: 安装

npm i body-parser

第二步:导入 body-parser 包

const bodyParser = require('body-parser');

第三步:获取中间件函数

// 解析 json 格式的请求体中间件
const jsonParser = bodyParser.json();

// 解析 querystring 格式请求体的中间件
const urlencodedParser = bodyParser.urlencoded({extended: true});

第四步:设置路由中间件,然后使用 request.body 来获取请求体数据

app.post('/login', urlencodedParser, (req, res) => {
    console.log(req.body); // { username: '111', password: '222' }
    res.send('获取用户数据')
})

六、路由模块化

把路由按照功能点进行模块化管理

// homeRouter.js
// 1、引用express
const express = require('express');
// 创建路由对象
const router = express.Router();
// 创建路由规则
// 创建路由
router.get('/home', (req, res) => {
    res.send('前台首页')
})
xxxx
xxxx
xxxx
// 暴露router
module.exports = router;

//其他模块同上


// 主文件 express.js
const homeRouter = require('./routes/homeRouter');
const adminRouter = require('./routes/adminRouter');
app.use(homeRouter);
app.use(adminRouter);

七、EJS 模版引擎

7.1 什么是模版引擎

模版引擎时分离用户界面和业务数据的一种技术

7.2 什么是 EJS

EJS 是一个高效的 javascript 的模版引擎 官网:ejs.co/ 中文站:ejs.bootcss.com/

7.3 EJS 初体验

下载 EJS

npm i ejs --save
// 引入 ejs
const ejs = require('ejs');
// 定义数据
let eat = '吃很多';
// ejs 解析模版返回结构
// <%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
let test = ejs.render('<%= eat %>', {eat});
console.log(test)

7.4 EJS 列表渲染

// 列表渲染
// 输出一个 ul li结构
const eatList = ['猕猴桃', '绿豆饼', '提拉米苏', '奥利奥'];
let result = ejs.render(`
<ul>
    <% eatList.forEach(item => { %>  // <% 内写js代码 %> 开始
    <li><%= item %></li> // 包裹内为循环部分,<%= item %> 数据赋值
    <% }) %>  // 这里结束
</ul>
`, { eatList });

// 标签内容写在html里⬇️
// let html = fs.readFileSync('./index.html').toString();
// let result = ejs.render(html, { eatList });

console.log(result);

7.5 EJS 条件渲染

//  条件渲染
/**
 * 通过 isLogin 决定最终的输出内容
 * true  输出  <span>欢迎回来</span>
 * false 输出  <button>登陆</button> <button>注册</button>
 */

// 变量
let isLogin = false;
let result = ejs.render(`
    <% if(isLogin){ %>
    <span>欢迎回来</span>
    <% }else{ %>
    <button>登陆</button> <button>注册</button>
    <% } %>
`, { isLogin });

// 标签内容写在html里⬇️
// let html = fs.readFileSync('./index.html').toString();
// let result = ejs.render(html, { isLogin });

console.log(result);

7.6 express中使用 EJS

// 导入 express
const express = require('express');
// 导入path
const path = require('path');
// 创建应用对象
const app = express();
// 1、设置模版引擎
app.set('view engine', 'ejs'); // 设置当前模版引擎为ejs 
// 2、设置模版文件存放位置  模版文件:具有模版语法内容的文件
app.set('views', path.resolve(__dirname, './views'));

// 创建路由
app.get('/home', (req, res)=>{
// 3、 render 响应
// res.render('模版文件名', '数据')
let eat = '吃很多';
res.render('home', {eat})
// 4、创建模版文件
// 在views文件夹下创建 home.ejs  后缀是 .ejs 不要写错
// home.ejs写入要渲染的数据
})

// 监听端口
app.listen(8080, () => {
    console.log('启动')
})

// home.ejs 内容
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h2>今天<%= eat %></h2>
</body>

</html>

八、express 应用程序生成器 express-generator

官网:www.expressjs.com.cn/starter/gen…

使用时可以在文件夹下 终端输入 express -e 文件夹名称 快速创建基本骨架