全书目录

第六篇:Nuxt 完全指南 —— 全媒体演播中心宇宙

第十一章:数据获取 —— 直播内容、预录内容、互动请求,路线不一样

2 分钟 521 字 第 138 / 962 个阅读单元

Nuxt 官方文档对数据获取的主线已经非常清楚:

  • $fetch
  • useFetch
  • useAsyncData

很多人学不明白,不是 API 看不懂,而是心智没立住。

先看最重要的关系:

text
$fetch
├── 最简单的请求函数
├── 更适合事件触发
└── 单独用在 setup 里可能双取

useFetch
├── 基于 $fetch
├── SSR 安全
├── 会把服务端数据带到客户端 payload
└── 最适合页面初始数据

useAsyncData
├── 更通用的异步包装层
├── 更细粒度控制
└── 适合复杂组合查询
#1. useFetch —— 栏目开播时就要准备好的数据
vue
<script setup lang="ts">
const { data, status, error, refresh } = await useFetch('/api/news')
</script>

<template>
  <div v-if="status === 'pending'">新闻加载中...</div>
  <div v-else-if="error">加载失败</div>
  <ul v-else>
    <li v-for="item in data" :key="item.id">
      {{ item.title }}
    </li>
  </ul>
</template>

Nuxt 官方强调:它会避免“服务端取一次、客户端水合再取一次”的双重请求问题。

#2. $fetch —— 用户点击后才发出的互动请求
vue
<script setup lang="ts">
async function subscribeChannel() {
  await $fetch('/api/subscriptions', {
    method: 'POST',
    body: {
      channel: 'news'
    }
  })
}
</script>

<template>
  <button @click="subscribeChannel">订阅栏目</button>
</template>

适合:

  • 按钮点击
  • 表单提交
  • 用户触发后的请求

不适合直接拿来当“首屏主数据”方案。

#3. useAsyncData —— 多路内容汇总编排
vue
<script setup lang="ts">
const { data } = await useAsyncData('home-dashboard', async () => {
  const [headline, ranking] = await Promise.all([
    $fetch('/api/headline'),
    $fetch('/api/ranking')
  ])

  return { headline, ranking }
})
</script>

当你需要:

  • 聚合多个接口
  • 自定义 key
  • 自定义 transform
  • 更灵活的缓存策略

就该优先想到 useAsyncData

#4. lazyserver: falsepick 这些选项到底在干什么?

官方文档里这部分很实用,可以翻成大白话:

  • lazy: true:别挡住整页跳转,先过去再慢慢补数据
  • server: false:这个数据别在服务端取,只在浏览器取
  • pick:接口返回很多字段,但只把真要用的字段塞进 payload
  • transform:在进入页面前先把结果整理好
vue
<script setup lang="ts">
const { data: posts, status } = useFetch('/api/posts', {
  lazy: true,
  pick: ['title', 'slug']
})
</script>
#5. 一个铁律:别把数据获取写成玄学
text
首屏关键数据 → useFetch / useAsyncData
用户事件触发 → $fetch
复杂聚合逻辑 → useAsyncData
非首屏、非 SEO 关键 → lazy + server:false 可考虑