Nuxt3.7 数据获取($fetch、useFetch、useAsyncData)详解

Nuxt提供了一个内置的数据获取库($fetch)和两个组合式(useFetchuseAsyncData)。

在本文中,我们将学习Nuxt 3中可用的不同数据获取方法以及何时使用它们。

$fetch

Nuxt内置了数据获取库ofetch,它基于fetch API构建,并提供了一些方便的功能,例如:

  • 在节点、浏览器和Web Workers上工作。
  • 智能解析响应中的JSON和本机值。
  • 当response.ok为false时,自动抛出错误并提供友好的错误消息和紧凑的堆栈(隐藏内部细节)。
  • 如果发生错误,自动重试请求。
  • 你可以提供异步拦截器来钩入ofetch调用的生命周期事件。
  • 你可以使用$fetch别名在整个应用程序中使用ofetch:
const todos = await $fetch('/api/todos').catch((error) => error.data)

useFetch

useFetch是在组件设置函数中处理数据获取最简单的方法。

<script setup>
const { data, error, pending, refresh } = await useFetch('/api/todos')
</script>

<template>
  <span v-if="pending">加载中...</
span>
  <span v-else-if="data">Todos: {{ data }}</span>
  <span v-else-if="error">错误: {{ error }}</span>
  <button @click="refresh">刷新</button>
</template>

useFetch返回三个响应式变量和一个函数:

  • data:包含传入的异步函数的结果的响应式变量。
  • error:包含有关请求错误的信息的响应式错误对象。
  • pending:一个响应式布尔值,指示请求是否正在进行中。
  • refresh/execute:一个用于刷新处理程序函数返回的数据的函数。默认情况下,Nuxt会等待刷新完成后才能再次执行。

useFetch负责在API调用在服务器上执行时将数据转发到客户端。这样,当页面进行水合(hydrates)时,客户端不需要在客户端上重新获取相同的数据。我们可以通过useNuxtApp.payload()来检查此有效负载;Nuxt DevTools会在有效负载选项卡中可视化此数据。

useFetch还通过使用键来缓存API响应来减少API调用。键是基于URL和fetch选项自动生成的。useFetch组合式会自动导入,可以在设置函数、生命周期钩子和插件或路由中间件中使用。

我们可以在URL字符串中使用ref的值,以确保在响应式变量更改时更新组件:

const todoId = ref('uuid')
const { data: tracks, pending, error } = useFetch(() => `/api/todos/${todoId.value}`)

如果todoId的值发生变化,URL将相应更新,并重新获取数据。

Options(选项)

useFetch接受一组选项作为最后一个参数,可用于控制组合式的行为。

Lazy(惰性加载)

数据获取组合式将在使用VueSuspense时自动等待异步函数解析完成后再导航到新页面。Nuxt在幕后使用Vue的<Suspense>组件来确保在每个异步数据可用于视图之前不会导航。

然而,如果你想在客户端导航时绕过此行为,可以使用lazy选项:

<script setup>
const { pending, data: todos } = useFetch('/api/todos', {
  lazytrue,
})
</script>

<template>
  <div v-if="pending">加载中...</
div>
  <div v-else>
    <div v-for="todo in todos">
      {{ todo.name }}
    </div>
  </div>

</template>

在这种情况下,需要使用pending值手动处理加载状态。

或者,可以使用useLazyFetch选项,它是实现相同结果的便捷方法:

const { pending, data: todos } = useLazyFetch('/api/todos')

Client-only(仅在客户端执行)

默认情况下,数据获取组合式会在客户端和服务器环境中执行其异步函数。如果要将执行限制为仅在客户端端执行,可以将server选项设置为false

const { pending, data: posts } = useFetch('/api/comments', {
  lazytrue,
  serverfalse,
})

这在与lazy选项结合使用时特别有用,用于不需要在初始渲染期间加载的数据,例如非SEO敏感数据。

警告:如果你没有在服务器上获取数据(例如使用server: false),则在水合过程完成之前,数据将不会被获取。这意味着,即使在客户端上等待useFetch,数据变量仍将在<script setup>中继续为null。

Minimize payload size(减小有效负载大小)

pick选项可以帮助你通过选择要从组合式返回的字段来减小存储在HTML文档中的有效负载大小:

<script setup>
const { data: todos } = await useFetch('/api/todos', {
  pick: ['id''name'],
})
</script>

<template>
  <div v-for="todo in todos">
    <span>{{ todo.name }}</
span>
    <span>{{ todo.id }}</span>
  </div>
</
template>

如果要获得更多控制或迭代多个对象,可以利用transform函数来修改查询结果:

const { data: todos } = await useFetch('/api/todos', {
  transform(todos) => {
    return todos.map((todo) => ({ name: todo.title, id: todo.description }))
  },
})

Refetching(重新获取数据)

要手动获取或更新数据,可以使用组合式提供的executerefresh函数:

<script setup>
const { data, error, execute, refresh } = await useFetch('/api/todos')
</script>

<template>
  <div>
    <p>{{ data }}</
p>
    <button @click="refresh">刷线数据</button>
  </div>
</
template>

这两个函数的作用是相同的,但在使用immediate: false时,execute更符合。当immediate选项设置为false(默认为true)时,它会阻止立即发出请求。

利用watch选项,可以在其他响应式值发生更改时重新运行获取函数:

const count = ref(1)

const { data, error, refresh } = await useFetch('/api/todos', {
  watch: [count],
})

使用refresh和watch选项的场景选择:

  • 当你知道服务器端的数据已被修改,并且需要相应地更新客户端端的数据时,请使用refresh()。
  • 当用户修改需要发送到服务器的参数时,请将这些参数设置为watch源。例如,如果要使用搜索参数过滤API结果,请watch该参数。这样可以确保每当用户更改查询时,都会从API重新加载新鲜且准确的数据。

查询搜索参数

使用query选项,您可以在查询中包含搜索参数:

const queryValue = ref('anyValue')

const { data, pending, error, refresh } = await useFetch('/api/todos', {
  query: { queryKey: queryValue, anotherQueryKey'anotherQueryValue' },
})

该选项是ofetch的扩展,并利用ufo生成URL。提供的对象会自动转换为字符串格式。

拦截器

可以定义异步拦截器来钩入API调用的生命周期事件:

const { data, pending, error, refresh } = await useFetch('/api/todo', {
  onRequest({ request, options }) {},
  onRequestError({ request, options, error }) {},
  onResponse({ request, response, options }) {},
  onResponseError({ request, response, options }) {},
})

这些选项由内置的ofetch库提供。

useAsyncData

useFetch用于从给定的URL获取数据,而useAsyncData允许进行更复杂的逻辑处理。实际上,useFetch(url)几乎等同于useAsyncData(url, () => $fetch(url)),为最常见的用例提供了更简化的开发体验。

但是,在某些情况下,使用useFetch组合式可能不合适,例如当CMS或第三方服务提供自己的查询层时。在这种情况下,可以使用useAsyncData来封装调用,并仍然享受组合式提供的好处:

const { data, error } = await useAsyncData('getTodos', () => fetchTodos())

useAsyncData中,第一个参数用作缓存从第二个参数(查询函数)获取的响应的唯一键。你也可以省略此参数并直接传递查询函数本身。在这种情况下,唯一键将自动生成。

注意:useAsyncDatauseFetch提供相同的返回值类型,并接受共享的选项集作为最后一个参数。这些选项允许您自定义组合式的行为,包括导航阻止、缓存和执行控制。

总结

让我们总结一下,何时应该使用哪种数据获取方法:

  • fetch函数适用于基于用户交互启动网络请求的情况。建议在将数据发送到事件处理程序、仅执行客户端逻辑或与useAsyncData组合使用时使用fetch
  • useFetch组合式是在组件的设置函数中处理数据获取的最简单方法。
  • 如果您需要更精确地控制数据获取过程,可以选择使用useAsyncData结合$fetch


原文始发于微信公众号(大前端编程教学):Nuxt3.7 数据获取($fetch、useFetch、useAsyncData)详解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/224504.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!