Nuxt 3 笔记:数据获取
方法
在 setup 阶段和生命周期钩子内可以使用以下方法:
useFetchuseLazyFetchuseAsyncDatauseLazyAsyncData
useFetch()可以认为是对useAsyncData()+$fetch()的简化包装。
$fetch()方法就是一个简单的请求方法,没有其它逻辑。通常在useAsyncData()内部使用,或者也可以在客户端使用。
Lazy
在上述四个方法中,带 Lazy 字样的方法是普通方法的语法糖,包了一个 lazy: true 的选项进去。
<template>
<div>
{{ pending ? 'Loading' : count }}
</div>
</template>
// <script setup>
const { pending, data: count } = useLazyAsyncData('count', () => $fetch('/api/count'))
watch(count, (newCount) => {
// ...
})
在上面的例子中,await useLazyAsyncData() 得到的返回值就像是一个 Promise(但并不是,只是理念类似)。通过返回值的 pending 可以判断其状态——由于在服务端并不会发出请求,因此 pending 是 true,且 data 为 null。
虽然 data 并没有拿到真正的值,但我们可以 watch 它,等待它获取真正的值。
API
useAsyncData()/useFetch()
这两个 API 如果没有在服务端获取数据(设置选项 server: false),则只会在水合之后获取数据。这意味着,即使你在客户端 await useAsyncData()/useFetch(),在 <script setup> 中 data 会保持为 null。(待确认)
问题:lazy 选项和 server 选项有什么区别?
server选项只影响着陆阶段的请求。server: false强制请求在浏览器端(水后之后)发出。但server: true并不能保证请求在服务器端发出,因为在 SPA 阶段,请求总是在浏览器端发出。lazy选项只影响 SPA 阶段的导航效果。lazy: false强制页面在请求完成之前不更新,也就是说,页面在请求期间是卡在那里的。而在lazy: true的状态下,data会经历一个从null到拿到真实数据的变化过程。(lazy: true并不会导致着陆页面的请求在浏览器端发出——着陆阶段默认都是在服务器端发请求,除非有server: false这个选项。)
useNuxtData()
可以随时获取 4 个请求方法缓存的数据。
// 请求接口,获取数据,产生缓存
const { data } = await useFetch('/api/posts', { key: 'posts' })
// 从缓存中取数据
const { data: posts } = useNuxtData('posts')
$fetch()
是 Nuxt 3 推荐的发起 HTTP 请求的方法,用于替代 Nuxt 2 时代的 @nuxt/http 和 @nuxtjs/axios。
在 SSR 期间,如果用 $fetch() 去请求一个内部 API 路由,则会直接调用相关的函数,省去发起接口调用的消耗。
刷新
refresh()
在 useFetch() 的返回结果中有一个 refresh() 方法。当请求参数有变化时(比如翻页就是一个典型场景,page 参数会变化),就可以调用这个 refresh() 方法来获取新数据。所以它的作用并不是重新请求一次老数据,而是发起一个查询条件有变化的新请求。
这些变化的参数通常是响应式的,所以 refresh() 方法不接收这些变化的参数。
我们不需要关心 refresh() 的返回值,这说明上述所有 4 个请求方法的返回的 data 是响应式的。
refresh() 可接收一个 { dedupe: true } 参数,它表示如果相同请求已经发过,则忽略。
refreshNuxtData()
这个工具方法可以清除上述 4 个请求方法的缓存,并立即触发一次刷新。
同构
传递客户端 Cookie
在 SSR 阶段的请求是由服务器发出的,因此不会携带客户端的 Cookie 等请求头。我们可以用 useRequestHeaders() 来转发客户端请求头。
const headers = useRequestHeaders(['cookie'])
const { data } = await useFetch('/api/me', { headers })
可以看到这里指定了一个白名单(['cookie']),因为有些请求头是不应该转发的,我们只应该转发那些真正需要的。
传递 Cookie 到客户端
SSR 阶段发出的请求可能会收到写 cookie 的响应,此时需要把 cookie 写到客户端,整个链路才是完整的。
我们需要手工完成这个操作,示意代码参见这里: https://nuxt.com/docs/getting-started/data-fetching#example-pass-cookies-from-server-side-api-calls-on-ssr-response
最佳实践
请求方法拿到的数据会全量写入页面中(payload 由后端传递给前端),增加页面体积,因此我们需要把不需要的字段剔除掉。可以用 { pick: ['key1', 'key2'] } 参数来挑选需要保留的字段。
相关链接:
- https://nuxt.com/docs/getting-started/data-fetching
- https://nuxt.com/docs/api/composables/use-async-data
- https://nuxt.com/docs/api/composables/use-fetch
- https://nuxt.com/docs/api/composables/use-lazy-async-data
- https://nuxt.com/docs/api/composables/use-lazy-fetch