Nuxt内置4个函数来处理数据:useFetch
,useLazyFetch
, useAsyncData
, useLazyAsyncData
。这些函数都只能在setup
代码块或者Vue生命周期函数中使用。
在Nuxt的页面、组件和插件中,无论客户端还是服务端,都可以使用useFetch
调用接口获取数据。
useFetch
是对useAsyncData
和$fetch
的封装。
示例:
<script setup>
const { data: count } = await useFetch('/api/count')
</script>
<template>
Page visits: {{ count }}
</template>
这个组合式函数等同于使用useFetch
时带上lzey: true
参数。也就是说,函数是异步的,不会阻塞页面跳转。这意味着你需要处理数据初始时默认为null的情况,如下示例:
<template>
<!-- you will need to handle a loading state -->
<div v-if="pending">
Loading ...
</div>
<div v-else>
<div v-for="post in posts">
<!-- do something -->
</div>
</div>
</template>
<script setup>
const { pending, data: posts } = useLazyFetch('/api/posts')
watch(posts, (newPosts) => {
// 因为posts初始值为null,你并不能马上在模板里使用它,但是你可以watch它的变化
})
</script>
在页面、组件或者插件中,你可以通过useAsyncData
获取需要异步处理的数据。
useAsyncData
用来处理比较复杂的异步场景.useFetch
则是useAsyncData
的语法糖,大致等同于useAsyncData(url, () => $fetch(url))
。
示例: server/api/count.ts
let counter = 0
export default defineEventHandler(() => {
counter++
return counter
})
app.vue
<script setup>
const { data } = await useAsyncData('count', () => $fetch('/api/count'))
</script>
<template>
Page visits: {{ data }}
</template>
等同于useAsyncData
并使用lazy: true
参数。
useLazyAsyncData
不阻塞页面跳转,但是需要手动处理初始数据为null的情况(如同上面useLazyFetch
)
示例:
<template>
<div>
{{ pending ? 'Loading' : count }}
</div>
</template>
<script setup>
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))
watch(count, (newCount) => {
// Because count starts out null, you won't have access
// to its contents immediately, but you can watch it.
})
</script>
接口返回的数据,如果不符合前端需要的结构,可以用transform
方法进行转换。我们推荐多使用transform
来精简接口返回值,只保留在页面中能用到的数据,以提升页面性能。
示例:
<script setup>
const { data: users } = await useAsyncData(
"users",
() => $fetch('/api/users'),
{
transform: (users) =>
users.map((user) => ({
id: user.id,
fullName: `${user.firstName} ${user.surname}`,
})),
}
);
</script>
<template>
<div>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.fullName }}
</li>
</ul>
</div>
</template>
useFetch
返回的refresh
方法,可以用来刷新数据(再次调用接口)
<script setup>
const page = ref(1)
const { data: users, pending, refresh, error } = await useFetch(() => `users?page=${page.value}&take=6`, { baseURL: config.API_BASE_URL }
)
function previous() {
page.value--
refresh()
}
function next() {
page.value++
refresh()
}
</script>
清除useAsyncData
、useLazyAsyncData
、useFetch
和useLazyFetch
的缓存,然后再次调用接口。这个方法仅针对当前页面有效。
<template>
<div>
{{ pending ? 'Loading' : count }}
</div>
<button @click="refresh">Refresh</button>
</template>
<script setup>
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))
const refresh = () => refreshNuxtData('count')
</script>
清除所有页面使用useAsyncData
和useFetch
的缓存和pending状态。
$fetch
Nuxt在ofetch的基础上封装了全局方法$fetch
,可以在Vue应用和API中使用。
在Vue组件中,我们推荐使用useFetch
或者useAsyncData + $fetch
,而不是直接使用$fetch
。因为在组件中直接使用$fetch
,容易造成两次接口调用(服务端一次,客户端一次)
示例:
<script setup>
// During SSR data is fetched twice, one on the server and one on the client.
const dataTwice = await $fetch("/api/item")
// During SSR data is fetched only on the server side and transferred to the client.
const { data } = await useAsyncData('item', () => $fetch('/api/item'))
// You can also useFetch as shortcut of useAsyncData + $fetch
const { data } = await useFetch('/api/item')
</script>