挺早之前就想写个 api 接口服务,封装下自己收集的一些 api 接口,以便调用,正好最近在接触 SSR 框架,所以就使用 Nuxt3 来编写该项目。
在线地址: API-Service
开源地址: kuizuo/api-service
如果你已经了解过 Nuxt3 与运行过程,那么可以直接跳转至 实战
npx nuxi init nuxt3-app
可能会安装不上 会提示 could not fetch remote https://github.com/nuxt/starter
,大概率就是本地电脑无法访问 github,这时候科学上网都不一定好使,这里建议尝试更换下网络或设置 host 文件。
安装完毕后,根据提示安装依赖与启动项目
初始的 nuxt3 项目及其简单,甚至没有 page、components、assets 等目录。
关于 nuxt3 本文不做过多介绍,本文只对部分进行介绍。nuxt 已经发布快 1 年了,相信外面很多相关介绍文章。
Nuxt3 介绍
自动导入
nuxt.js 与 next.js 极其相像,但 nuxt 却精简许多,这归功于 nuxt 的自动导入,这可以让你无需导入像 vue 中的 ref 等等函数,导入组件等操作,不过前提是代码文件位置要符合 nuxt 规范。如果你尝试使用过 vite 的一些自动导入插件,其效果是一样的,只不过 nuxt 都已经配置好,开箱即用。
文件路由
pages 为 nuxt 中页面所存放的位置,会将 pages 目录下的文件(.vue
, .js
, .jsx
, .ts
or .tsx
) 与路由映射,像pages/index.vue
映射为 /
,然后在 app.vue 中通过<NuxtPage/>
来展示 pages。
要注意,pages 下的文件一定要有根节点,不然在路由切换的时候可能会出现问题(事实上建议所以的 vue 组件都有根节点,虽说 vue3 允许多个根节点,但或多或少存在一定问题)
至于动态路由与嵌套路由,文档说明的比较详细了,这里就不费口舌了
服务引擎
Nuxt3 中的的 api 接口服务引擎使用的是⚗️ Nitro 的 JavaScript 服务,使用的是h3的 http 框架(相当于 hook 版的 http 框架),不过文档不是特别详细,很多东西都要琢磨。(这个框架是真的相对冷门,之前都未曾 听闻过)
关于 Nuxt3 的服务具体可以看 Nuxt 3 - Server Routes,这里演示部分代码
创建一个服务,创建文件server/api/hello.ts
export default defineEventHandler(event => {
return 'hello nuxt'
})
请求 http://localhost/api/hello 便可得到hello nuxt
,在 event 可以得到 req 与 res 对象。不过在 req 身上是获取不到 query 和 body 的,这里需要使用 h3 提供的 hooks,如useMethod()
,useQuery()
,useBody()
来获取,例如。
export default eventHandler(async event => {
const body = await useBody(event)
return `User updated!`
})
这与传统的 node 的 http 框架不同点就是 query,body 这些参数不是从函数的上下文(context)取,而是通过 hook 来获取,所以这就是我为什么我说这相当于 hook 版的框架。关于这些 api,可以点我查看
数据获取
定义完了接口,那必然是要获取数据的,nuxt.js 有四种方式来获取数据,不过主要就二种useFetch
与useAsyncData
,另外两种是其懒加载形式。
像上面定义了 helloworld 接口就可以像下面这样使用
<script setup>
const { data } = await useFetch('/api/hello')
console.log(data) // hello nuxt
</script>
<template>
{{ data }}
</template>
useAsyncData
<script setup>
const { data } = await useAsyncData('hello', () => $fetch('/api/hello'))
console.log(data) // hello nuxt
</script>
<template>
{{ data }}
</template>
至于 useAsyncData 与 useFetch 有什么区别的话,如果请求的是 url 资源,那么建议使用 useFetch,如果请求的是其他来源的资源,就使用 useAsyncData。可以说在请求 url 资源时,两者是等价的,如下
useFetch(url) <==> useAsyncData(url, () => $fetch(url))
那么如何 SSR(服务端渲染)呢? nuxt3
默认是全 SSR
的渲染模式,也就是说在上面的数据请求后就是 SSR 渲染,客户端接受到的也就是带有数据页面。
如果要使用传统的客户端渲染只需要填加一个 options 的 server 参数为 false 即可,如
const { data } = await useFetch('/api/hello', { server: false })
自己尝试下将 server 切换,然后打开控制台->网络中查看 Fetch/XHR 中是否有和数据相关的请求便可知道是在服务端发送的请求数据,还是客户端发送的数据。