Nuxt 3内置了Nitro服务器,我们可以在这里编写服务器端代码。Nitro在内部使用unjs/h3来创建服务器和处理路由。在本文中,我们将在Nitro服务器引擎和h3路由处理程序的帮助下创建API。我们还将了解如何使用h3实用程序来处理请求、响应和错误。
本文是对Nuxt3的defineEventHandler方法的拓展说明,官方文档地址:https://nuxt.com/docs/guide/directory-structure/server
创建一个Nuxt3应用
npx nuxi init my-app
之后,使用控制台进入创建好的项目并安装依赖
cd my-app
#npm
npm i
npm run dev
#yarn
yarn
yarn dev
Nuxt 3为客户端提供了基于文件的路由系统,因此,我们需要在根目录中创建 server
文件夹,用于存放API代码。
假设你的项目目录结构如下:
|- server/
| |- api/
|- app.vue
|- nuxt.config.ts
|- package.json
|- yarn.lock
|- README.md
|- tsconfig.json
写一个基本的事件处理器
在 server/api
目录内创建一个 hello.ts
//server/api/hello.ts
export default defineEventHandler((event) => {
return {
hello: 'world'
}
})
现在,我们可以在页面中请求这个接口:
<script setup>
const { data } = await useFetch('/api/hello')
</script>
<template>
<pre>{{ data }}</pre>
</template>
处理不同类型的请求
以文件名后缀进行区分
//server/api/hello.get.ts
//此方法会接受来自/api/hello的get请求
export default defineEventHandler((event) => {
return {
msg: '我是GET请求'
}
})
//server/api/hello.post.ts
//此方法会接受来自/api/hello的post请求
export default defineEventHandler((event) => {
return {
msg: '我是POST请求'
}
})
//server/api/hello.put.ts
//此方法会接受来自/api/hello的put请求
export default defineEventHandler((event) => {
return {
msg: '我是PUT请求'
}
})
//server/api/hello.delete.ts
//此方法会接受来自/api/hello的delete请求
export default defineEventHandler((event) => {
return {
msg: '我是DELETE请求'
}
})
方法内进行判断
//server/api/hello.ts
//此方法会接受来自/api/hello的所有类型请求,并在方法内进行判断
export default defineEventHandler((event) => {
if(event.req.method === 'GET') {
return {
msg: '我是DELETE请求'
}
}
if(event.req.method === 'POST') {
return {
msg: '我是POST请求'
}
}
if(event.req.method === 'PUT') {
return {
msg: '我是PUT请求'
}
}
if(event.req.method === 'DELETE') {
return {
msg: '我是DELETE请求'
}
}
})
在一个文件内定义多个接口
在上面的服务器api示例中,我们创建了对应的文件来捕获请求,这种依赖于文件结构的来维护的模式,随着代码量的增长,会逐渐难以维护,值得庆幸的是,我们可以借助Nuxt3的Catch-all Route轻易实现。
依照Nuxt3路由规则,在 server/api
目录下创建 […].ts
文件匹配所有 /api
开头的请求。
//server/api/[...].ts
import {
createApp,
createRouter,
useBody,
useBase,
sendError,
createError,
} from 'h3';
const app = createApp({
debug: false,
onError: (error, event) => {
sendError(event, error);
},
});
const router = createRouter();
router
.get('/hello', defineEventHandler(() => {
return {
msg: 'hello',
};
}))
.post('/world', async (req, res) => {
const body = await useBody(req);
const { name } = body;
if (!name) {
const err = createError({
statusCode: 403,
statusMessage: '访问被拒绝',
data: 'name required',
});
sendError(res, err);
}
return {
msg: 'hello'
}
})
.get('/hello/:id', (req, res) => {
return {
id: req.context.params.id
};
})
.put('/world/:id', defineEventHandler(async (event) => {
const body = await useBody(event);
const { content } = body;
return {
id: event.context.params.id,
body: { content },
};
}))
.delete('/world/:id', (req, res) => {
res.statusCode = 202;
return { success: true };
});
app.use(router);
export default useBase('/api', app);