Express 是一个精简、灵活的 Node.js 的 Web 应用程序开发框架,为 Web 和移动应用程序提供了一组强大的功能,使用 Express 可以快速地开发一个 Web 应用。
通过使用 Express 可以实现用中间件来响应 HTTP 请求,通过路由来定义不同请求的响应函数,还可以使用模板引擎来输出 HTML 页面。
Express 没有数据库的概念,留给第三方 Node 模块实现,因此几乎可以接入任何数据库。
1.1 安装 Express
代码语言:javascript复制npm install -g express-generator
安装成功后可通过 express --version 查看版本:
这里安装的 express-generator 是一个应用生成器工具,通过它可以快速创建一个应用的骨架,为快速创建 Node.js 项目提供便利。
1.2 使用 Express 创建项目
1.2.1 创建项目
1)进入工作目录,创建一个名为 hello 的 Express 项目:
2)进入 hello 项目,安装依赖包:
3)执行 npm start 启动项目,然后在浏览器中输入 http://localhost:3000/ 查看:
1.2.2 Express 项目结构分析
目录结构:
1.2.3 应用主文件 app.js
app.js 文件相当于项目启动的主入口文件,有一些公共方法和服务器配置等信息:
代码语言:javascript复制// http错误处理模块
var createError = require('http-errors');
// 引入Express
var express = require('express');
// 引入path
var path = require('path');
// 引入cookie处理
var cookieParser = require('cookie-parser');
//引入日志模块
var logger = require('morgan');
// 引入路由目录中的index.js文件
var indexRouter = require('./routes/index');
// 引入路由目录中的users.js文件
var usersRouter = require('./routes/users');
// 创建Express应用
var app = express();
// 定义页面目录
app.set('views', path.join(__dirname, 'views'));
// 定义页面模板引擎
app.set('view engine', 'jade');
// 定义日志打印级别
app.use(logger('dev'));
// 定义JSON格式处理数据
app.use(express.json());
// 定义使用urlencode处理数据及querystring模块解析数据
app.use(express.urlencoded({ extended: false }));
// 定义cookie处理对象
app.use(cookieParser());
// 定义静态资源目录public
app.use(express.static(path.join(__dirname, 'public')));
// 定义指向index.js的路由
app.use('/', indexRouter);
// 定义指向users.js的路由
app.use('/users', usersRouter);
// 定义404错误处理
app.use(function(req, res, next) {
next(createError(404));
});
// 定义其他错误处理
app.use(function(err, req, res, next) {
// 设置locals,只在开发环境生效
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// 返回错误http状态码
res.status(err.status || 500);
// 渲染错误页面
res.render('error');
});
module.exports = app;
1.3 Express 路由
1.3.1 GET 请求路由
代码语言:javascript复制//routes/index.js
// 引入Express
var express = require('express');
// 引入Express路由对象
var router = express.Router();
// 首页路由
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
// 导出路由
module.exports = router;
每次更改过路由文件都要重新启动项目才会生效,这样降低开发效率,可以使用 nodemon 工具,安装命令:
代码语言:javascript复制npm install -g nodemon
安装好后,修改 package.json 文件:
代码语言:javascript复制"scripts": {
//"start": "node ./bin/www"
"start": "nodemon ./bin/www"
},
这样在路由文件被更改并保存后,会自动重启项目,并可以立刻在浏览器中看到更改后的运行结果。
1.3.2 其他请求方式的路由
HTTP 请求方式除了 GET 外,还有 POST、PUT、DELETE 等方式:
代码语言:javascript复制// POST请求方式
router.post('/word', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
// PUT请求方式
router.put('/word', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
// DELETE请求方式
router.delete('/word', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
1.3.3 路由匹配规则
前面演示的路由匹配都是完整匹配,即定义 “/word” ,在浏览器中要输入 “/word” 才能匹配到。
在 Express 中,还支持模糊匹配:
代码语言:javascript复制//能够匹配/west、/wet
router.get('/wes?t', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
//能够匹配/west、/weest、/weeest等
router.get('/we st', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
//能够匹配/west、/wt等
router.get('/w(es)?t', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
//能够匹配/west、/we123st、/wexxxst等
router.get('/w*st', (req, res, next) => {
res.render('index', {title: 'hello word'});
});
在 Express 中,还支持正则表达式:
代码语言:javascript复制//能够匹配路径中包含west的内容,如/west、/aawest、/westee等
router.get(/west/, (req, res, next) => {
res.render('index', {title: 'hello word'});
});
1.3.4 中间件
这里的中间件是指一些处理方法的合集,Express 其实就是一个路由和中间件合成的 Web 框架。
可以在中间件中定义一个验证方法,然后在需要验证的接口路由上添加验证中间件,完成接口的验证。上面定义路由时,传入的函数就是 Express 中的中间件。
在 Express 中,中间件会被 Express 传入3个参数:
1)req:请求数据对象 Request;
2)res:返回数据对象 Response;
3)next:下一步函数。
1.4 Express 页面
1.4.1 更换模板引擎
Express 默认的模板引擎是 jade,我们可以把它替换成更简洁、高效的 art-template。
1)首先安装依赖包:
代码语言:javascript复制npm install -S art-template express-art-template
2)安装好后,修改 app.js 文件:
代码语言:javascript复制// app.set('view engine', 'jade');
app.engine('html', require('express-art-template'));
app.set('view engine', 'html');
3)在 views 目录下新建一个 index.html 的测试页面:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>我是一个HTML文件</h1>
</body>
</html>
4)运行后浏览器查看效果:
1.4.2 渲染数据到页面上
1)在 views 目录下的 index.html 页面添加:
代码语言:javascript复制<h2>这是title的值:{{title}}</h2>
2)浏览器查看效果:
1.4.3 条件渲染
修改 index.js 的路由文件:
代码语言:javascript复制// 首页路由
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Hello',
name: '爱学习的程序媛',
age: 30,
happy: true
});
});
1)基本条件渲染
修改 index.html 页面文件:
代码语言:javascript复制{{if age < 30}}
<p>大家好,我是{{name}},我今年{{age}}岁,很高兴认识大家!</p>
{{/if}}
{{if age >= 30}}
<p>大家好,我是{{name}},很高兴认识大家!</p>
{{/if}}
2)嵌套条件渲染
修改 index.html 页面文件:
代码语言:javascript复制{{if age >= 30}}
<p>大家好,我是{{name}},
{{if happy}}
<span>很高兴认识大家!</span>
{{/if}}
</p>
{{/if}}
1.4.4 循环渲染
修改 index.js 的路由文件:
代码语言:javascript复制// 首页路由
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Hello',
list: [
{id: 1, content: '今天星期一'},
{id: 2, content: '好好学习'},
{id: 3, content: '天天向上'}
],
targetId: 2
});
});
1)基本循环渲染
修改 index.html 页面文件:
代码语言:javascript复制{{each list as item}}
<p>{{item.id ': ' item.content}}</p>
{{/each}}
2)循环渲染结合条件渲染
修改 index.html 页面文件:
代码语言:javascript复制{{each list as item}}
{{if item.id === targetId}}
<p style="color: #eb4bd8;">{{item.id ': ' item.content}}</p>
{{else}}
<p>{{item.id ': ' item.content}}</p>
{{/if}}
{{/each}}
1.5 请求对象 Request
1)Request.url 属性:获取请求地址
拿到的是请求地址端口号后面的值。
2)Request.query 属性:获取 GET 请求参数
获取 GET 请求参数,它是一个对象,包含路由中每个查询字符串参数的属性,如果没有查询字符串,则为空对象。
只能获取 GET 请求方式,或者拼接在 url 后面的参数,不能获取其他请求方式的参数。
3)Request.body 属性:获取 POST 请求参数
POST请求不能直接在浏览器中请求,可以使用 Postman 工具进行测试。
4)Request.params 属性:获取 URL 中的自定义参数
Express 把通过 URL 传入的参数存到了 Request.params 属性中,同时它又是一个对象,包含所有自定义的 URL 参数,可以很轻松地获取到任意一个参数。
5)Request.headers 属性:获取请求头数据
6)Request.cookies 属性:获取客户端 cookie
1.6 返回对象 Response
1)Response.render() 方法:渲染页面
它有三个参数:
代码语言:javascript复制res.render('index');
res.render('index', (err, html) => {
res.send(html);
})
res.render('index', {title: 'hello'}, (err, html) => {
//渲染完毕的回调按时
})
2)Response.send() 方法:发送 HTTP 请求
发送一个 HTTP 响应至前端,它只接收一个参数,这个参数可以是任意类型。它之所以可以接收任意类型的参数,是因为执行这个方法返回的时候它会自动设置响应头部数据类型,即响应头里的 Content-Type 字段。
① 当参数是 Buffer 对象时,设置 Content-Type 为 application/octet-stream:
代码语言:javascript复制res.send(new Buffer('<p>html</p>'));
② 当参数为 String 时,设置 Content-Type 为 text/html:
代码语言:javascript复制res.send('<p>some html</p>');
③ 当参数为 Array 或 Object 时,Express 以 JSON 表示响应,设置 Content-Type 为 application/json:
代码语言:javascript复制res.send({name: 'cxh'});
res.send([1, 2, 3]);
3)Response.json() 方法:返回 JSON 格式的数据
只接收一个参数,可以是任意的 JSON 格式类型,包括对象、数组、字符串、布尔值和数字,甚至可以将其他值转换为 JSON 格式类型:
代码语言:javascript复制res.json(null);
res.json({user: 'cxh'});
res.status(500).json({error: 'message'});
4)Response.status() 方法:设定 HTTP 状态码
使用该方法时,后面需跟 end() 或 send() 或 json() 等,因为它并不返回结果,只是设置一个状态:
代码语言:javascript复制res.status(403).end();
5)Response.redirect() 方法:跳转指定路由
使用该方法可以跳转到指定的路由:
代码语言:javascript复制res.redirect('/word');
还提供了设置 HTTP 状态码的参数:
代码语言:javascript复制res.redirect(301, '/word');