Express 是一个 Node.js Web 框架。 其 API 共有 5 类,分别是:
- express()
- Application
- Request
- Response
- Router
以上 5 类 API 的使用,文中通过创建 express-demo 来熟悉。
在 express-demo 下运行 yarn init -y 创建默认的 package.json,运行 yarn add express 安装 express;创建 app.js,添加以下代码:
const express = require('express')
const app = express()
app.use((req, res, next) => {
res.send('hi')
})
app.listen(5001, () => {
console.log('listen 5001')
})
创建了 express 服务,监听 5001 端口,运行 node app.js 即可启动服务,在浏览器输入 http://localhost:5001/ 可以看到如下:
看到 hi 说明运行正常。以下示例均由 postman 构造请求。
express()
用于内置中间件。express() 创建了一个 Express 应用,即 demo 中的 app。
共 7 个 API,此处介绍 3 个常用的 API
- express.json()
- express.static()
- express.Router()
express.json()
假如请求体即 req.body 是 json,会将完整的 json 解析出来,返回解析 json 的中间件。
下面示例是未添加 express.json() 的代码:
app.use((req, res, next) => {
console.log('req.body')
console.log(req.body)
res.send('hi')
next()
})
请求如下:
终端打印如下:
可以看到没添加时打印结果是 undefined。当添加 express.json() 时,代码如下:
app.use(express.json())
app.use((req, res, next) => {
console.log('req.body')
console.log(req.body)
res.send('hi')
next()
})
再次进行相同的请求,终端打印结果如下:
express.static(root)
Express 使用 express.static 中间件函数设置静态目录的顺序来查找文件。将包含静态资源文件的目录传递给 express.static 中间件函数,以便开始直接提供这些文件。express.static 默认做一个静态服务器,参数 root 是放置静态资源的根目录,只要访问路径在 root 目录下,就会在 root 目录下查找,没有则在外面查找。
根目录下创建 yyy 目录,在 yyy 中创建 index.html。以 root 为 'yyy' 为例,代码如下:
app.use(express.static('yyy'))
app.use((req, res, next) => {
res.send('hi')
})
要访问 yyy/index.html 只要在浏览器地址栏输入 http://localhost:5001/index.html 即可,由于 http://localhost:5001/ 默认就是 http://localhost:5001/index.html ,得到请求如下:
已不再是原来的 hi,如果请求的是 http://localhost:5001/xxx 则结果如下:
如需使用多个静态目录文件,则需多次调用 express.static 中间件函数。
如果要为静态资源文件创建虚拟路径前缀,可以在 app.use 中指定,假设可以通过访问 http://localhost:5001/static/index.html 得到 yyy/index.html,代码如下:
app.use('/static', express.static('yyy'))
请求如下:
express.Router()
用于创建 router 对象,与 Router API 配合使用,具体使用见 Router API 部分。
Application
用于应用设置,如模板配置、中间件、挂载路由。也就是本文例子中的 app(主应用)。
共 22 个 API,此处介绍 3 个常用的 API
- app.set()
- app.METHOD()
- app.use()
app.set()
app.set(name, value) 将 value 赋值给 name 用于存储数据,可以通过 app.get(name) 获得值;也有一些指定的 name,比如 case sensitive routing(大小写敏感) 、views(模板文件所在目录)、view engine(视图引擎模板)等。
以是否区分路由大小写为例,代码如下:
app.set('case sensitive routing', true) // 区分路由大小写
app.get('/style.css', (req, res, next) => {
res.send('style.css')
})
app.get('/STYLE.css', (req, res, next) => {
res.send('STYLE.css')
})
请求如下:
可以看到 /style.css 和 /STYLE.css 得到的结果是不一样的,说明设置生效。
也可以用 app.set 来配置模板,通常与 app.render 配合使用,此文不展开详情介绍介绍,可参考官网指南使用模板引擎。
app.METHOD()
也就是 app.get / app.post / app.delete / app.put 等请求,比如 get 用法 app.get(path, callback),参数分别是路径和该路径下执行的回调。
例如在 /test 路径下的 get/post/delete/patch 方法请求,代码如下:
app.get('/test', (req, res, next) => {
res.send('get /test')
})
app.post('/test', (req, res, next) => {
res.send('post /test')
})
app.delete('/test', (req, res, next) => {
res.send('delete /test')
})
app.patch('/test', (req, res, next) => {
res.send('patch /test')
})
请求如下:
app.use()
用于挂载中间件,或执行指定路径下的方法。例如,上面代码可以写成如下代码:
app.use('/test', (req, res, next) => {
if(req.method === 'GET'){
res.send('get /test')
}
if(req.method === 'POST'){
res.send('post /test')
}
if(req.method === 'DELETE'){
res.send('delete /test')
}
if(req.method === 'PATCH'){
res.send('patch /test')
}
next()
})
请求得到的结果与 app.get / app.post / app.delete / app.patch 一致, 相当于 app.use 的简写方式,不同之处在于 app.use 可用于任何方法,而不指定某种具体的请求方法。当不指定路径时,app.use 可用于任意的请求和路径,好比请求是 /xxx 时,得到的响应时 hi,如下:
Request
用于操作请求。app.use((req, res, next) => {}) 中的 req 就代表 http 请求。
共 28 个 API,此处介绍 2 个常用的 API
- req.get()
- req.param()
req.get()
返回请求头的字段,比如 req.get('Content-Type'),代码如下:
app.use((req, res, next) => {
console.log(req.get('Content-Type'))
res.send('hi')
})
请求如下:
终端打印如下:
req.param()
req.param(name) 返回 req.params | req.body | req.query 中的 name 值。从 Express 4.11 起开始使用 req.params,req.body,req.query 代替 req.param。
app.use('/:name', (req, res, next) => {
console.log(req.params)
console.log(req.body)
console.log(req.query)
console.log(req.param('name'))
res.send('hi')
})
请求如下:
终端打印如下:
Response
用于操作响应。app.use((req, res, next) => {}) 中的 res 就代表 http 响应。
共 24 个 API,此处介绍 3 个常用的 API
- res.send()
- res.status()
- res.format()
res.send()
发送响应体,内容可以是 Buffer、String、Boolean、Array。res.send 是非流式操作,一次发完所有内容,与此同时还会自动设置 header。
代码如下:
app.use((req, res, next) => {
res.send('<p>p标签</p>')
})
请求如下:
响应头:
res.status()
设置响应状态码,可以链式调用。
比如返回404,代码如下:
app.use((req, res, next) => {
res.status(404).send('404 not found')
})
请求如下:
res.format()
根据请求头中的 Accept 类型返回相应的内容。
代码如下:
app.get('/test', (req, res, next) => {
res.format({
'text/plain': function () {
res.send('hey')
},
'text/html': function () {
res.send('<p>hey</p>')
},
'application/json': function () {
res.send({ message: 'hey' })
},
default: function () {
res.status(406).send('Not Acceptable')
}
})
})
请求如下:
- 设置请求头 Accept 为 text/plain
- 设置请求头 Accept 为 text/html
- 设置请求头 Accept 为 application/json
- 设置请求头 Accept 为 application/xml,不属于代码中的任一类型,故发送默认内容
Router
用于操作路由。可以被认为是一个 mini app,挂载到 app,前面提到 Router 常跟 express.Router() 一起配合使用。
比如有一个 /user 路径是列出所有用户的页面,/user/:id 是根据 id 找出的某个具体的用户信息,/user/:id/edit 是根据 id 编辑某个具体的用户信息,代码可以如下:
app.get('/user', (req, res, next) => {
res.send('/user')
})
app.get('/user/:id', (req, res, next) => {
res.send('/user/:id')
})
app.get('/user/:id/edit', (req, res, next) => {
res.send('/user/:id/edit')
})
这样写无疑是有点重复的,都是 /user 路径下的路由,那么我们可以把这些子路径都挂载到 /user 下即可,app.js 中跟 /user 路由有关的代码改写成:
// app.js
app.use('/user', userRouter)
根目录下创建 routes 文件夹,在 routes 下添加 user.js 用于放置跟 /user 有关的路由,代码如下:
const express = require('express')
const router = express.Router()
router.get('/', (req, res, next) => {
res.send('/user')
})
router.get('/:id', (req, res, next) => {
res.send('/user/:id')
})
router.get('/:id/edit', (req, res, next) => {
res.send('/user/:id/edit')
})
module.exports = router
同时将导出的 router 导入到 app.js 中,代码如下:
const userRouter = require('./routes/user')
请求如下:
可以看出 /user,/user/1,/user/1/eidt 得到的返回都不相同。从而得知,可以把不同根路径下的路由分成几个不同的部分挂载到 app 下,方便书写和维护。
以上就是此文的全部内容,有问题欢迎指出,谢谢阅读~