返回介绍

数据获取 Data Fetching

发布于 2024-04-18 00:42:19 字数 6544 浏览 0 评论 0 收藏 0

Nuxt 提供可组合项来处理应用程序中的数据获取。

Nuxt 附带两个可组合项和一个内置库,用于在浏览器或服务器环境中执行数据获取: useFetchuseAsyncData$fetch

它们一起使用,可确保跨环境兼容性和高效缓存,并避免重复的网络调用。

useFetch 是在 Nuxt 中执行 API 调用的最直接的方法。

如果需要更细粒度的控制,可以单独使用useAsyncData$fetch

这两个可组合项共享一组通用的选项和模式,我们将在最后几节中详细介绍这些选项和模式。

为什么要使用特定的可组合项?

当使用像 Nuxt 这样可以在客户端和服务器环境上执行调用和渲染页面的框架时,必须解决一些挑战。 这就是 Nuxt 提供可组合项来包装查询的原因。

网络调用重复

useFetchuseAsyncData 都使用密钥来缓存 API 响应并进一步减少 API 调用。 稍后我们将详细介绍如何使该缓存失效。

Suspense

useFetch 是执行数据获取的最直接的方法。 它是useAsyncData可组合项和$fetch实用程序的包装器。

app.vue
<script setup>
const { data: count } = await useFetch('/api/count')
</script>

<template>
  Page visits: {{ count }}
</template>
相关阅读:composables > use-fetch

$fetch

ofetch 库构建在 fetch API 之上,并为其添加了方便的功能:

  • 在浏览器、节点或工作环境中以相同的方式工作
  • 自动响应解析
  • 错误处理
  • 自动重试
  • 拦截器

阅读 ofetch 的完整文档

ofetch 由 Nuxt 自动导入并由 useFetch 可组合项使用。

它还可以通过$fetch别名在整个应用程序中使用:

ts
const users = await $fetch('/api/users').catch((error) => error.data)

请注意,仅使用 $fetch 不会提供本页第一部分 中描述的好处。 建议在将数据发布到事件处理程序、执行仅客户端逻辑时使用$fetch,或与useAsyncData结合使用。

相关阅读:utils > dollarfetch

useAsyncData

useFetch 接收 URL 并获取该数据,而 useAsyncData 可能有更复杂的逻辑 。 useFetch(url) 几乎等同于 useAsyncData(url, () => $fetch(url)) - 它是最常见用例的开发人员体验糖。

在某些情况下,使用 useFetch 可组合项并不合适,例如,当 CMS 或第三方提供自己的查询层时。 在这种情况下,您可以使用 useAsyncData 来包装您的调用,并仍然保留可组合项提供的好处:

ts
const { data, error } = await useAsyncData('users', () => myGetFunction('users'))

useAsyncData 的第一个参数是用于缓存第二个参数(查询函数)的响应的唯一键。 通过直接传递查询函数可以忽略该参数。 在这种情况下,它将自动生成。

相关阅读:composables > use-async-data

Options

useAsyncDatauseFetch 返回相同的对象类型并接受一组通用选项 他们最后的争论。 它们可以帮助您控制可组合项的行为,例如导航阻止、缓存或执行。

Lazy

当我们在浏览器中调用 $fetch 时,像 cookie 这样的用户标头将被直接发送到 API。 但在服务器端渲染期间,由于“$fetch”请求在服务器“内部”发生,因此它不包含用户的浏览器 cookie,也不传递来自 fetch 响应的 cookie。

将客户端标头传递给 API

Nuxt 3 提供了一种在选项 API 中执行asyncData获取的方法。 您必须将组件定义包装在defineNuxtComponent中才能正常工作。

vue
<script>
export default defineNuxtComponent({
  /* 使用 fetchKey 选项提供唯一的密钥 */
  fetchKey: 'hello',
  async asyncData () {
    return {
      hello: await $fetch('/api/hello')
    }
  }
})
</script>

使用 <script setup lang="ts"> 是在 Nuxt 3 中声明 Vue 组件的推荐方法。

相关阅读:utils > define-nuxt-component

序列化

server目录获取数据时,使用JSON.stringify对响应进行序列化。 然而,由于序列化仅限于 JavaScript 基元类型,Nuxt 会尽力转换 $fetchuseFetch 的返回类型以匹配实际值。

您可以在此处了解有关JSON.stringify限制的更多信息。

Example

server/api/foo.ts
export default defineEventHandler(() => {
  return new Date()
})
app.vue
<script setup lang="ts">
// 即使我们返回了 Date 对象,“data”的类型也被推断为字符串
const { data } = await useFetch('/api/foo')
</script>

自定义序列化器函数

要自定义序列化行为,您可以在返回的对象上定义“toJSON”函数。 如果您定义了一个“toJSON”方法,Nuxt 将尊重该函数的返回类型,并且不会尝试转换类型。

server/api/bar.ts
export default defineEventHandler(() => {
  const data = {
    createdAt: new Date(),

    toJSON() {
      return {
        createdAt: {
          year: this.createdAt.getFullYear(),
          month: this.createdAt.getMonth(),
          day: this.createdAt.getDate(),
        },
      }
    },
  }
  return data
})
app.vue
<script setup lang="ts">
// Type of `data` is inferred as
// {
//   createdAt: {
//     year: number
//     month: number
//     day: number
//   }
// }
const { data } = await useFetch('/api/bar')
</script>

使用替代序列化器

Nuxt 目前不支持JSON.stringify的替代序列化器。 但是,您可以将有效负载作为普通字符串返回,并利用toJSON方法来维护类型安全。

在下面的示例中,我们使用 superjson 作为序列化器。

server/api/superjson.ts
import superjson from 'superjson'

export default defineEventHandler(() => {
  const data = {
    createdAt: new Date(),

    // 解决类型转换问题
    toJSON() {
      return this
    }
  }

  // 使用 superjson 将输出序列化为字符串
  return superjson.stringify(data) as unknown as typeof data
})
app.vue
<script setup lang="ts">
import superjson from 'superjson'

// `date` 被推断为 { createdAt: Date } 并且您可以安全地使用 Date 对象方法
const { data } = await useFetch('/api/superjson', {
  transform: (value) => {
    return superjson.parse(value as unknown as string)
  },
})
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文