Nuxt提供了一个内置的数据获取库($fetch
)和两个组合式(useFetch
和useAsyncData
)。
在本文中,我们将学习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(惰性加载)
数据获取组合式将在使用Vue的Suspense
时自动等待异步函数解析完成后再导航到新页面。Nuxt在幕后使用Vue的<Suspense>
组件来确保在每个异步数据可用于视图之前不会导航。
然而,如果你想在客户端导航时绕过此行为,可以使用lazy
选项:
<script setup>
const { pending, data: todos } = useFetch('/api/todos', {
lazy: true,
})
</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', {
lazy: true,
server: false,
})
这在与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(重新获取数据)
要手动获取或更新数据,可以使用组合式提供的execute
或refresh
函数:
<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
中,第一个参数用作缓存从第二个参数(查询函数)获取的响应的唯一键。你也可以省略此参数并直接传递查询函数本身。在这种情况下,唯一键将自动生成。
注意:useAsyncData
和useFetch
提供相同的返回值类型,并接受共享的选项集作为最后一个参数。这些选项允许您自定义组合式的行为,包括导航阻止、缓存和执行控制。
总结
让我们总结一下,何时应该使用哪种数据获取方法:
-
fetch
函数适用于基于用户交互启动网络请求的情况。建议在将数据发送到事件处理程序、仅执行客户端逻辑或与useAsyncData
组合使用时使用fetch
。 -
useFetch
组合式是在组件的设置函数中处理数据获取的最简单方法。 -
如果您需要更精确地控制数据获取过程,可以选择使用 useAsyncData
结合$fetch
。
原文始发于微信公众号(大前端编程教学):Nuxt3.7 数据获取($fetch、useFetch、useAsyncData)详解
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/224504.html