数据获取
Nuxt 提供了组合函数来处理应用程序中的数据获取
useFetch
:是在组件设置函数中处理数据获取的最简单的方法$fetch
:可以根据用户交互进行网络请求useAsyncData
:结合$fetch
提供更精细的控制
useFetch
和 useAsyncData
共享一组常见的选项和模式,在后面的章节中我们将详细介绍。
在此之前,首先要知道为什么需要这些组合函数。
useFetch
useFetch
组合函数是执行数据获取的最简单的方法。
- 这里要使用解构赋值来获取数据,因为
useFetch
返回一个响应对象,该对象包含data
和error
等等属性。
<script setup lang="ts">
const { data: count } = await useFetch("/api/count");
</script>
<template> 页面访问量:{{ count }} </template>
$fetch
Nuxt 包括了 ofetch
库,并且作为全局别名 $fetch
自动导入到应用程序中。它是 useFetch
在幕后使用的工具
使用方法
一般就是点击事件获取数据
和 useAsyncData 结合使用
<script setup lang="ts">
const login = () => {
const result = await $fetch("/auth/login", {
method: "POST",
body: {
username: "username",
password: "password",
},
});
};
</script>
<template>
<div>
<button @click="login">登录</button>
</div>
</template>
INFO
请注意,仅使用 $fetch
将不会提供 网络请求重复和导航阻止。建议在提交数据到事件处理程序时使用 $fetch
,在客户端逻辑中使用,或与 useAsyncData
结合使用。
useAsyncData
seAsyncData
组合函数负责封装异步逻辑并在解析完成后返回结果。
事实上,useFetch(url)
几乎等同于 useAsyncData(url, () => $fetch(url))
- 它是为最常见的用例提供的开发者体验糖。
在某些情况下,使用 useFetch
组合函数是不合适的,例如当 CMS 或第三方提供自己的查询层时。在这种情况下,您可以使用 useAsyncData
来封装您的调用,并仍然保持组合函数提供的好处。
useAsyncData
的第一个参数是用于缓存第二个参数(查询函数)的响应的唯一键。如果直接传递查询函数,则可以忽略该参数。在这种情况下,它将自动生成。
特别注意第一个参数不能重复:一般用接口地址作为键位
单独
const { data, error } = await useAsyncData("users", () =>
myGetFunction("users")
);
组合
useAsyncData
组合函数是包装和等待多个 useFetch
完成,并获取每个结果的绝佳方式。
const { data: discounts, pending } = await useAsyncData(
"cart-discount",
async () => {
const [coupons, offers] = await Promise.all([
$fetch("/cart/coupons"),
$fetch("/cart/offers"),
]);
return {
coupons,
offers,
};
}
);
- 页面使用的时候就是
<h1>{{discount.offers}}</h1>
<h2>{{discount.coupons}}</h2>
选项
懒加载(lazy)
默认情况下,数据获取的组合函数会在异步函数解析完成之前使用 Vue 的 Suspense 进行页面导航。通过使用 lazy
选项,可以忽略此功能在客户端导航时的使用。在这种情况下,你需要手动处理加载状态,使用 pending
值。
- 组件里面
通过 pedding 来控制加载状态
<script setup lang="ts">
const { pending, data: posts } = useFetch("/api/posts", {
lazy: true,
});
</script>
<template>
<!-- 你需要处理加载状态 -->
<div v-if="pending">加载中...</div>
<div v-else>
<div v-for="post in posts">
<!-- 做一些操作 -->
</div>
</div>
</template>
你还可以使用useLazyFetch
和useLazyAsyncData
作为方便的方法来执行相同的操作。
const { pending, data: posts } = useLazyFetch("/api/posts");
- 仅仅在客户端中调用
通过server
选项来控制
const { data: posts } = useFetch("/api/posts", {
server: false,
lazy: true,
});
获取有效字段(pick)
- 通过
pick
选项来控制
<script setup lang="ts">
/* 仅选择模板中使用的字段 */
const { data: mountain } = await useFetch("/api/mountains/everest", {
pick: ["title", "description"],
});
</script>
<template>
<h1>{{ mountain.title }}</h1>
<p>{{ mountain.description }}</p>
</template>
刷新(refresh)
- 如果要手动获取或刷新数据,请使用组合函数提供的
execute
或refresh
函数。
<script setup lang="ts">
const { data, error, execute, refresh } = await useFetch("/api/users");
</script>
<template>
<div>
<p>{{ data }}</p>
<button @click="refresh">刷新数据</button>
</div>
</template>
发送参数(query)
- 通过 query 选项来控制
const id = ref(null);
const { data, pending } = useLazyFetch("/api/user", {
query: {
user_id: id,
},
});
状态
<script setup lang="ts">
const { data, error, execute, pending, status } = await useLazyFetch(
"/api/comments"
);
</script>
<template>
<div v-if="status === 'idle'">
<button @click="execute">获取数据</button>
</div>
<div v-else-if="pending">加载评论中...</div>
<div v-else>{{ data }}</div>
</template>
为了更精细的控制,status 分成了以下几种
idle
:获取未开始pending
:获取已开始但尚未完成error
:获取失败success
:获取成功完成
传递请求头和 Cookie
当我们在浏览器中调用 $fetch
时,用户的请求头(如 cookie)会直接发送到 API。但在服务器端渲染期间,由于 $fetch
请求在服务器内部进行,它不包含用户浏览器的 Cookie
,也不会传递来自获取响应的 Cookie
。
将客户端请求头传递到 API
我们可以使用 useRequestHeaders
来访问和代理服务器端的 Cookie
到 API。
下面的示例将请求头添加到同构的 $fetch
调用中
以确保 API 端点能够访问用户最初发送的相同 cookie
请求头。
<script setup lang="ts">
const headers = useRequestHeaders(["cookie"]);
const { data } = await useFetch("/api/me", { headers });
</script>