Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nuxt 3 笔记:数据获取 #15

Open
cssmagic opened this issue Mar 17, 2024 · 0 comments
Open

Nuxt 3 笔记:数据获取 #15

cssmagic opened this issue Mar 17, 2024 · 0 comments
Labels

Comments

@cssmagic
Copy link
Owner

方法

在 setup 阶段和生命周期钩子内可以使用以下方法:

  • useFetch
  • useLazyFetch
  • useAsyncData
  • useLazyAsyncData

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 可以判断其状态——由于在服务端并不会发出请求,因此 pendingtrue,且 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'] } 参数来挑选需要保留的字段。


相关链接:

@cssmagic cssmagic added the Nuxt3 label Mar 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant