Nuxt 数据获取

本文将介绍 Nuxt 中的 3 个数据获取 API,分析其设计缘由和各自的优势。

一、数据获取的问题及其解决方案

在 Nuxt 中,由于其特殊性,存在着若干个与数据获取相关的问题,如下:

1. 接口调用方式问题

在 Nuxt 中,由于同时存在多种渲染模式,代码有可能运行于服务端和客户端,因此不得不考虑接口的调用时机。

在渲染模式为 SSR2.0 时:

  • 服务端进行首屏渲染时,渲染者与接口处理者为同一个程序,只需要进行本地方法调用即可
  • 在后续以浏览器为主导的 SPA 模式中,接口调用发生在浏览器,需要发送 HTTP 请求至服务端处理

2. 接口重复调用问题

若渲染方式为 SSR2.0,则有可能发生 “接口重复调用问题”。具体来说,针对首屏:

  • 在服务端中,为了构建页面,首先进行了第一次接口调用
  • 浏览器渲染首屏页面后,进一步进行 SPA 化,在此过程中,由于 Vue 实例的状态并不会从服务器传输到浏览器,因此,浏览器必须要再次调用接口以获取数据

使用 Nuxt 提供的 useFetchuseAsyncData,可以借助 Nuxt 的 payload 传递数据,并在需要时优先从中提取,从而避免 “接口重复调用问题”。

3. 异步组件加载问题

若组件为异步组件(即组件存在异步依赖),则组件存在加载状态、最终状态等不同的状态。这就要求开发者不仅要编写最终状态下的界面,还需要额外编写等待异步依赖时的加载界面。为了简化这一过程,Vue3 引入了 Suspense 组件。它允许组件 “等待” 某些异步操作完成,并在此期间显示一个备用内容(如加载指示器),直到异步操作完成,主内容才被渲染。

在路由跳转时,Nuxt 会利用 Suspense 组件,在下一页面的组件加载完成之前,延缓页面的跳转,从而避免 “异步组件加载问题”。

为了达到这一目的,要求开发者使用 async setup,并确保通过 await 关键字等待每一个网络请求的完成。Nuxt 提供的数据获取 API 能够很好地实现这一点。

4. 解决方案

为了解决这些问题,Nuxt 提供了 useFetchuseAsyncData$fetch 等 API。

二、useFetch

useFetch 是 Nuxt 最推荐的数据获取方式,它是 useAsyncData$fetch 的结合。

useFetch(url) 等效于 useAsyncData(() => $fetch(url))

useFetch 的返回值格式如下:

1
2
3
4
5
6
7
8
9
{
"data": "异步数据",
"pending": "布尔值,指示数据是否仍在获取",
"refresh": "函数,用于重新获取数据",
"execute": "函数,用于重新获取数据",
"clear": "函数,用于取消异步数据的获取",
"error": "对象,当数据获取失败时展示错误",
"status": "字符串,指示数据请求状态,包括'idle'、'pending'、'success'、'error'"
}

useFetch 存在一个可选参数,该参数为对象,可以用于控制请求,包括缓存与否、调用时机等。

三、useAsyncData

useAsyncData 负责处理异步数据,它将提供缓存功能,以避免异步数据的重复获取。

useAsyncData 接收两个参数,

  • key:
    • 唯一标识,用于缓存 fun 的结果
    • 可以不传递,将自动生成一个值
  • fun:
    • 查询函数,应该返回一个包含了异步数据的 Promise

useAsyncData 的返回值格式与 useFetch 相同。

useAsyncData 也存在一个与 useFetch 相同的可选参数。

四、$fetch

$fetch 解决了 “接口调用方式问题”,可以配合 Nuxt 解决 “异步组件加载问题”,并没有解决 “接口重复调用问题”。

因此,建议在以下两种前提下使用 $fetch

  • 只能由用户交互触发

    例如,请求需要用户手动点击按钮后才会发送,因此,”接口重复调用问题” 自然得到解决

  • useAsyncData 配合使用

参考