前言
这篇文章的诞生源于我之前的一个经历,我有一个比较好的点子,想把它实现出来,但是无奈自己只能写前端的部分,后端的接口却无从下手,学习JAVA
、Go
等周期又太长了;后面了解到了这个框架,对前端来说上手很自然,通过和MongoDB
数据库结合解决了我的后端需要;所以写这篇express
入门的文章也是为了解决和我之前遇到同样问题的朋友。
介绍
Express是一个基于Node.js平台,快速、开放、极简的Web开发框架:
- Web应用程序:Express 是一个保持最小规模的灵活的 Node.js Web 应用程序开发框架,为 Web 和移动应用程序提供一组强大的功能
- API:使用您所选择的各种 HTTP 实用工具和中间件,快速方便地创建强大的 API
- 性能:Express 提供精简的基本 Web 应用程序功能,而不会隐藏您了解和青睐的 Node.js 功能
- 框架:许多 流行的开发框架 都基于 Express 构建
基本使用
开始之前,请先在一个文件夹中,使用npm init
初始化项目,下载express
包,后续的操作都在这个文件夹中进行
Web服务
新建一个index.js
作为主文件
// 引入express
const express = require('express');
// 执行express
const app = express();
// 编写接口
app.get('/', (req, res, next) => {
// res.write('111');
// res.end();
// res.send = res.write+res.end
// res.send('111');
res.send(`
<html>
<h1>111</h1>
</html>
`);
});
// 监听3000端口
app.listen(3000, () => {
console.log('server start');
});
node index.js
执行上面文件,那么在http://localhost:3000/
根目录就能够看到页面内容:(此处将以上文件定义为入口文件)
这里要讲一下,上方代码中的API:
- get:编写一个get请求的接口
- get中第二个参数中的形参:
- res:请求相关内容(请求参数、请求地址、请求头等)
- req:相应相关内容(响应头设置、响应内容设置等)
- next(可选):如果有多个中间件时,可以调用
next()
传递到下一个中间件
- listen:监听端口
路由
经过上面的操作之后,页面内容显示了出来,但是只有一个页面,挺单调的;这里使用express.Router
来增加一个home
页面.
在根目录新建router
文件夹,然后在文件夹中新建js文件,命名为HomeRouter,写入以下内容:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('home 页面内容');
});
module.exports = router;
在入口文件引入它:
const HomeRouter = require('./router/HomeRouter');
...
app.use('/home', HomeRouter);
...
重新运行之后,访问/home
,就能看到如下内容:
除了显示页面内容,也可以在router中定义接口内容,比如这里我们在上面的HomeRouter
文件中加入一个get
接口:
router.get('/data', (req, res) => {
res.send([1, 2, 3]);
});
这时候访问/home/data
,就有以下效果:
也就是说,router
的功能既可以定义返回页面内容的接口,也可以定义返回数据的接口。
后续若是你真正的使用,可能会有userRouter
、LoginRouter
等等代表不同的接口,这时候router
文件夹就起到了集中统一管理的作用:
模版
到了这一步,你可能对于上面的直接返回页面内容有了疑问:以后复杂的页面不可能都用这种方式返回页面内容吧?
是的,你的感觉是对的,肯定不可能这样使用;所以接下来,就要引出EJS模版这个概念了。
EJS是一个用于Web开发的JavaScript模板引擎,允许用户使用HTML模板中的JavaScript代码生成动态HTML标记。
接下来,我们将上方的例子改造一下:
- 在这里先引入
ejs
包:
npm install ejs
- 在根目录创建文件夹
views
统一管理页面,在文件夹中创建两个文件:home.ejs
、login.ejs
// 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>
// 语法 <%= 值%>
home 传入的值 <%= data%>
</body>
</html>
// login.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>
login-html
// 语法 <%= 值%>
<h1>传入的值:<%=title%></h1>
<form action="/login" method="post">
<div>用户名:<input type="text" name="username" /></div>
<div>密码:<input type="password" name="password" /></div>
<div><input type="submit" value="登录" /></div>
</form>
</body>
</html>
- 修改
HomeRouter
,新增LoginRouter
// HomeRouter
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
// 渲染模版,并给模版传参
res.render('home', {data: 222}); // 找views文件夹下的home.ejs
});
module.exports = router;
// LoginRouter
const express = require('express');
const router = express.Router();
// 路由级别-响应前端的给请求
router.get('/', (req, res) => {
console.log(req.query, 'req');
// res.send('login根');
// 渲染模版,并给模版传参
res.render('login', {title: 222}); // 找views文件夹下的login.ejs
});
// 路由级别-响应前端的post请求
router.post('/', (req, res) => {
res.redirect('/home');
});
module.exports = router;
- 入口文件修改为如下内容:
const express = require('express');
const LoginRouter = require('./router/LoginRouter');
const HomeRouter = require('./router/HomeRouter');
const app = express();
// 配置模版引擎
app.set('views', './views');
app.set('view engine', 'ejs');
app.use('/login', LoginRouter);
app.use('/home', HomeRouter);
app.listen(3000, () => {
console.log('启动');
});
经过以上修改之后,访问/home
就是home.ejs
的内容,访问/login
就是login.ejs
的内容:
ok,效果出来了,梳理一下模版使用的知识点,如下:
express
使用ejs
的步骤:
- 引入ejs包
- 入口文件配置ejs
- router中使用
res.render
渲染ejs
路由传参
经过上面的例子,能够做到显示不同的页面了;在login
页面中,可以看到留了一个登录表单,LoginRouter
也预留了一个post
请求。没错,这一节要来讲一下路由传参(body
、query
)了,正好从获取post
参数开始讲。
配置解析请求体,在入口文件加入以下内容:
// 配置解析body参数(4.16.0 及以上的版本)
app.use(express.urlencoded({extended: false}));
app.use(express.json()); // json格式
在LoginRouter
中的post
接口中,添加一行代码:
console.log(req.body);
重新运行,输入帐号、密码,点击登录,在终端即可看到以下内容:
[Object: null prototype] { username: '111', password: '222' }
ok,获取query
参数就更简单了,不用配置,直接res.query
就可以查看内容;在HomeRouter
中添加一行代码:
console.log(req.query);
重新运行之后,访问这个地址http://localhost:3000/home?abc=111
终端就会出现以下内容:
{ abc: '111' }
那么,总结一下:
-
请求体参数:需要在主入口配置以下内容后,在
req.body
中获取到app.use(express.urlencoded({extended: false})); app.use(express.json());
-
query参数:无需配置,在
req.query
中获取到
中间件
在 Express 中,中间件(Middleware)是函数,用于处理请求和响应对象。在请求-响应周期中,中间件可以访问请求对象 (req
)、响应对象 (res
),以及下一个中间件函数,通过调用 next()
来传递控制权。
中间件主要有以下几种类型:
- 应用级中间件
- 路由级中间件
- 内置中间件
- 第三方中间件
中间件主要是用来处理一些系统层面的事情,例如登录校验、统一错误处理等等。
在主入口文件的头部位置,加入以下代码:
app.use((req, res, next) => {
console.log('应用级中间件');
next();
});
// 加了路径代表只有这个路径才执行
app.use('/home', (req, res, next) => {
console.log('路由级中间件');
next();
});
现在访问接口的时候,应用级中间件会触发,访问/home
的时候会同时触发应用级中间件和路由级中间件:
应用级中间件
路由级中间件
总结:中间件是express
的核心概念,能够处理一些系统层面的工作,然后将控制权交出去。
静态资源
express
提供了express.static
的方式来配置静态文件,例如:
app.use(express.static('public'));
访问的时候,不需要public,只需要localhost:3000/文件名,就能够访问到。
总结
到这里的话,express
的基本概念就讲解完毕了,文中带着你写了访问页面的接口、返回数据的接口、请求参数获取、路由分块等等功能;
你可以用它来写前后端一体的项目,也可以按标题说的作为一个后端来给你自己提供接口,写一点自己的东西。如果你有数据库需要的话,express
也可以和MongoDB
结合(有MongoDB
的需要,推荐一下这一篇《入门MongoDB,看这一篇文章就够了》);如果你有登录校验的需要,还可以JWT
与express
结合。
总之express
能做的事情还是很多的,是一个挺不错的框架,如果你对它的底层原理感兴趣的话,可以去研究一下Node.js
的http
模块。
ok,感谢你能看到这里,下一篇文章再见吧!