一、express 简单使用
- express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs.
com.cn/ - 简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)
新建一个文件夹,并初始化 npm,并安装 express
npm init npm i express
在文件夹中新建 index.js 文件
// 1. 导入 express const express = require('express'); // 2. 创建应用对象 const app = express(); // 3. 创建路由,请求方法是 get,请求路径是 /home 时 // 将会调用回调函数 app.get('/home', (req, res) => { res.end('hello express'); }); // 4. 监听端口,启动服务 app.listen(9000, () => { console.log('服务已经启动,9000端口监听中...'); });
运行项目(如果 index.js 内容有修改,需要重新启动项目,nodemon 可以解决这个问题,可以自行安装)
# 或者 nodemon index.js node index.js
在浏览器中输入
127.0.0.1:9000/home
,可以看到效果
二、路由
- 官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求
(一)路由的使用
- 一个路由的组成有
请求方法
,路径
和回调函数
组成 - express 中提供了一系列方法,可以很方便的使用路由,使用格式如下:
app.<method>(path,callback)
const express = require('express');
const app = express();
// 浏览器输入:http://127.0.0.1:9000/
app.get('/', (req, res) => {
res.end('home');
});
// post 可以通过发送一个表单请求进行测试
app.post('/login', (req, res) => {
res.end('登录成功');
});
// 请求方法不限制,只要请求路径一致即可
// 浏览器输入:http://127.0.0.1:9000/test
app.use('/test', (req, res) => {
res.end('test');
});
// 匹配所有请求, Express5 已经不支持如下写法
// app.all('*', (req, res) => {
// res.end('404 Not Found');
// });
// Express5
app.all('{*splat}', (req, res) => {
// 将捕获路径值
console.log(req.params.splat);
res.end('404 Not Found');
});
app.listen(9000, () => {
console.log('服务已经启动,9000端口监听中...');
});
(二)获取请求参数
express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式
const express = require('express'); const app = express(); // 浏览器中输入:http://127.0.0.1:9000/request?a=1&b=2#foot app.get('/request', (req, res) => { // 原生获取方式 console.log(req.method); // GET console.log(req.url); // /request?a=1&b=2 console.log(req.httpVersion); // 1.1 console.log(req.headers); // express 操作 console.log(req.path); // /request console.log(req.query); // { a: '1', b: '2' } console.log(req.ip); // 127.0.0.1 // 获取请求头 console.log(req.get('host')); // 127.0.0.1:9000 res.end('request ok'); }); app.listen(9000, () => { console.log('服务启动成功,9000端口监听中...'); });
(三)获取路由参数
路由参数指的是 URL 路径中的参数(数据)
const express = require('express'); const app = express(); // 浏览器中输入:http://127.0.0.1:9000/1234/5678.html app.get('/:id/:code.html', (req, res) => { res.send('商品详情, 商品 id 为' + req.params.id + ',code 为' + req.params.code ); }); app.listen(9000, () => { console.log('服务启动成功,9000端口监听中...'); });
三、express 响应设置
- express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式
const express = require('express');
const app = express();
app.get('/response', (req, res) => {
// 原生响应
// res.statusCode = 404
// res.statusMessage = 'not found123'
// res.setHeader('abc', 'cba')
// res.write('response ok\r\n')
// res.end('response ok2')
// express 响应
// res.status(500); // 设置响应状态码
// res.set('aaa', 'bbb'); // 设置响应头
// res.send('中文不乱码'); // 设置响应体
// 等同于
res.status(500).set('aaa', 'bbb').send('中文不乱码');
//其他响应
// res.redirect('http://baidu.com'); //重定向
// res.download('./package.json'); //下载响应
// res.json({ name: '张三', age: 18 }); //响应 JSON
// res.sendFile(__dirname + '/02.form.html'); //响应文件内容
});
app.listen(9000, () => {
console.log('服务启动成功,9000端口监听中...');
});
四、express 中间件
(一)基础
【1】什么是中间件
- 中间件(Middleware)本质是一个回调函数
中间件函数
可以像路由回调一样访问请求对象
(request),响应对象
(response)
【2】中间件的作用
中间件
的作用 就是 使用函数封装公共操作
,简化代码
(二)中间件的类型
中间件分为:全局中间件,路由中间件
【1】全局中间件
- 每一个请求到达服务端之后都会执行全局中间件函数
const express = require('express');
const app = express();
// 定义一个中间件
function recordMiddleware(req, res, next) {
console.log(`记录日志,请求url:${req.url},请求ip:${req.ip}`);
next();
}
// 应用中间件
app.use(recordMiddleware);
app.get('/home', (req, res) => {
res.send('home');
});
app.get('/login', (req, res) => {
res.send('login');
});
app.listen(9000, () => {
console.log('服务器启动成功,端口9000监听中...');
});
【2】路由中间件
如果 只需要对某一些路由进行功能封装 ,则就需要路由中间件
const express = require('express'); const app = express(); // 生命中间件 function checkCodeMiddleware(req, res, next) { const code = req.query.code; // 判断 code 是否等于 521 if (code === '521') { // 如果 code 等于 521,则调用 next() 方法,将请求转发给下一个中间件 // 如果没有下一个中间件则调用对应路由的回调 next(); } else { res.send('code 错误'); } } // 使用路由中间件 app.get('/home', checkCodeMiddleware, (req, res) => { // 中间件执行了 next 方法才会进入到该回调函数 res.send('home'); }); app.get('/admin', checkCodeMiddleware, (req, res) => { res.send('后台首页'); }); app.listen(9000, () => { console.log('服务器启动成功,端口9000监听中...'); });
【3】静态资源中间件
- express 内置处理静态资源的中间件
注意事项:
- index.html 文件为默认打开的资源
- 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
- 路由响应动态资源,静态资源中间件响应静态资源
const express = require('express');
const app = express();
// 设置静态资源中间件
// __dirname + '/public' 是静态资源所在的文件夹
// 如果public 文件夹中 /css/base.css 文件存在
// 在浏览器上直接输入 http://127.0.0.1:9000/css/base.css
// 可以访问到该文件
app.use(express.static(__dirname + '/public'));
// 如果请求url 为 http://127.0.0.1:9000/index.html
// public 文件夹中有 index.html 文件
// 该路由也可以响应 /index.html
// 这时候,会响应 public/index.html 文件,
// 因为 静态资源中间件 在路由前面
app.get('/index.html', (request, response) => {
response.send('首页');
});
app.listen(9000, () => {
console.log('服务器启动成功,端口9000监听中...');
});
(三)获取请求体数据 body-parser
- express 可以使用 body-parser 包处理请求体
安装 body-parser
npm i body-parser
使用 body-parser,新建 index.js 文件
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); // 解析 JSON 格式的请求体的中间件 // const jsonParser = bodyParser.json(); // 解析 querystring 格式请求体的中间件 const urlencodedParser = bodyParser.urlencoded({ extended: false }); // 显示登录页面 // 浏览器中输入:http://127.0.0.1:9000/login app.get('/login', (request, response) => { // 将登录页面发送给浏览器 response.sendFile(__dirname + '/form.html'); }); // 登录页面提交数据的位置 app.post('/login', urlencodedParser, (request, response) => { // urlencodedParser 中间件会将请求体中的数据放置在request.body console.log(request.body); // { username: 'admin', password: '123456' } response.send('登录成功'); }); app.listen(9000, () => { console.log('服务启动成功,端口9000监听中...'); });
index.js 文件所在目录新建 form.html 文件
<form action="http://localhost:9000/login" method="post"> <label> 用户名:<input type="text" name="username" /> </label> <label> 密码: <input type="password" name="password" /> </label> <input type="submit" value="提交" /> </form>
五、Router
- 什么是 Router
- express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。
- Router 作用
- 对路由进行模块化,更好的管理路由
新建 homeRouter.js 文件,放置所有路由
const express = require('express'); // 创建路由器对象 const router = express.Router(); // 在 router 对象身上添加路由 router.get('/', (req, res) => { res.send('get home'); }); router.get('/cart', (req, res) => { res.send('get cart'); }); // 导出 router module.exports = router;
homeRouter.js 文件所在文件夹中,新建 index.js 文件,作为入口文件,并引入 homeRouter.js 文件
const express = require('express'); const app = express(); // 引入子路由文件 const homeRouter = require('./homeRouter'); // 设置和使用中间件 app.use(homeRouter); app.listen(9000, () => { console.log('9000 端口启动....'); });
六、EJS 模板引擎
(一)基础
【1】 什么是模板引擎
- 模板引擎是分离 用户界面和业务数据 的一种技术
【2】什么是 EJS
- EJS 是一个高效的 Javascript 的模板引擎
- 官网: https://ejs.co/
- 中文站:https://ejs.bootcss.com/
(二)使用
【1】基础语法
在项目中安装 EJS
npm i ejs --save
创建 index.js 文件,在 js 中使用 ejs 中的语法
const ejs = require('ejs'); const fs = require('fs'); // 字符串渲染 let result = ejs.render('我的名字是<%= name %>', { name: '张三' }); console.log(result); // 列表渲染 const list = ['水浒传', '三国演义', '西游记', '红楼梦']; let result2 = ejs.render( `<ul> <% list.forEach(item => { %> <li><%= item %></li> <% }) %> </ul>`, { list } ); console.log(result2); // 条件渲染 const flag = 2; let result3 = ejs.render( ` <% if(flag === 1){ %> <h1>欢迎回来</h1> <% } else if(flag === 2){ %> <h1>请登录</h1> <% } else { %> <h1>请注册</h1> <% } %> `, { flag } ); console.log(result3); // 读取 html 文件,并替换里边的数据 const str = fs.readFileSync('./ejs.html'); const html = ejs.render(str.toString(), { name: '李四', list: list, flag }); console.log(html); // <p>我的名字是 李四</p>
在 index.js 文件同目录下创建 ejs.html 文件,用于在 html 文件中显示ejs语法
<p>我的名字是 <%= name%></p> <ul> <% list.forEach(item => { %> <li><%= item %></li> <% }) %> </ul> <% if(flag === 1){ %> <h1>欢迎回来</h1> <% } else if(flag === 2){ %> <h1>请登录</h1> <% } else { %> <h1>请注册</h1> <% } %>
【2】在 express 中使用 ejs
安装 ejs 和 express
npm i express npm i ejs --save
创建 index.js 文件,进行配置
const express = require('express'); const path = require('path'); const app = express(); // 将模板引擎设置为 ejs app.set('view engine', 'ejs'); // 设置模板文件的存放位置 app.set('views', path.resolve(__dirname, './views')); // 浏览器中输入:http://localhost:9000/home app.get('/home', (req, res) => { // 渲染模板文件 // res.render(模板文件名, 对应的数据) res.render('home', {title: '首页'}); }); app.listen(9000, () => { console.log('服务启动成功,9000端口监听中...'); });
在index.js 文件所在的文件夹中,创建 views 文件夹,用于存放模板文件
在 views 文件夹中创建 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><%= title %></h2> </body> </html>
七、express-generator 工具
- 通过应用生成器工具 express-generator 可以快速创建一个应用的骨架。
- https://www.expressjs.com.cn/starter/generator.html
全局安装 express-generator
npm install -g express-generator
使用如下命令,在某个文件夹中创建项目
express -e 文件夹名称
进入到项目所在文件夹,安装依赖
npm i
使用如下命令启动项目,由 package.json 可以看到入口文件是 bin/www 文件
npm run start
在浏览器中输入
http://localhost:3000/
可以看到项目已经运行了
八、处理文件上传
安装 formidable
# 也需要安装 ejs 和 express npm i formidable
新建 index.js 文件,用于处理上传的文件所存放的位置
const express = require('express'); const { formidable } = require('formidable'); const path = require('path'); const app = express(); const router = express.Router(); // 设置静态资源中间件:设置静态资源目录 app.use(express.static(__dirname + '/public')); // 设置模板引擎 ejs app.set('view engine', 'ejs'); app.set('views', path.resolve(__dirname, './views')); router.get('/', (req, res) => { // 渲染 views/form.ejs 文件 res.render('form'); }); router.post('/upload', (req, res) => { // 创建 form 对象 const form = formidable({ multiples: true, // 设置上传文件的报错目录 uploadDir: path.resolve(__dirname, './uploads'), // 保持文件后缀 keepExtensions: true, }); // 解析请求报文 form.parse(req, (err, fields, files) => { if (err) { next(err); return; } // console.log(fields); // { username: [ 'admin' ], password: [ '123' ] } // console.log(files); // 文件信息 // 让用户根据 url 查看自己上传的文件 res.send('/uploads/' + files.portrait[0].newFilename); }); }); // 应用路由 app.use(router); app.listen(9000, () => { console.log('9000 端口启动....'); });
新建 views 文件夹,并在其中新建 form.ejs 模板文件
<form action="http://localhost:9000/upload" method="post" enctype="multipart/form-data" > <label> 用户名:<input type="text" name="username" /> </label> <label> 密码:<input type="password" name="password" /> </label> <label> 头像: <input type="file" name="portrait" /> </label> <input type="submit" value="提交" /> </form>
新建 public 文件夹,并在其中新建 uploads 文件夹,用于存放用户提交的文件