概览

View source
Nuxt 数据获取基础与 Movk Nuxt API 系统的核心概念和架构设计

Nuxt 数据获取基础

Nuxt 提供三种数据获取方式,理解它们的区别有助于选择正确的 Movk Nuxt 封装。

  • $fetch :底层 HTTP 客户端,基于 ofetch,在服务端和客户端均可运行。
    // 用户点击时调用 -- 适合 $fetch
    async function handleSubmit() {
      const result = await $fetch('/api/login', {
        method: 'POST',
        body: { username, password }
      })
    }
    
  • useFetchuseAsyncData + $fetch 的语法糖封装
    // 页面加载时获取数据 -- 适合 useFetch
    const { data: posts, status, error } = await useFetch('/api/posts')
    
  • useAsyncData:最灵活的数据获取 composable。
    // 聚合多个接口 -- 适合 useAsyncData
    const { data } = await useAsyncData('dashboard', async () => {
      const [users, stats] = await Promise.all([
        $fetch('/api/users'),
        $fetch('/api/stats')
      ])
      return { users, stats }
    })
    

关键参数详解

useFetch(以及 useApiFetch)的三个核心参数决定了请求的执行时机和行为。

server

控制是否在服务端执行数据获取。默认 true

行为对比:

  • server: true(默认)-- SSR 时在服务端执行请求,数据通过 payload 传到客户端,客户端不再重复请求
  • server: false -- 仅在客户端执行。首次加载时数据在 hydration 完成后才开始获取,data 初始为 null

使用场景:

  • server: true -- SEO 相关数据、首屏需要展示的内容
  • server: false -- 非 SEO 敏感数据(用户评论、个性化推荐、统计数据),减轻服务端负担
// 文章列表需要 SEO -- server: true(默认)
const { data: posts } = await useApiFetch<Post[]>('/posts')

// 评论数据不需要 SSR -- server: false
const { data: comments } = useApiFetch('/comments', {
  server: false,
  lazy: true,
})
server: false 通常与 lazy: true 搭配使用,这正是 useClientApiFetch 的预设行为。

lazy

控制是否阻塞客户端导航。默认 false

行为对比:

  • lazy: false(默认)-- 通过 Vue Suspense 阻塞导航,等数据返回后才完成路由切换。用户看不到 loading 状态
  • lazy: true -- 不阻塞导航,页面立即显示,数据在后台获取。需要手动处理 loading 状态

使用场景:

  • lazy: false -- 页面核心数据,没有数据页面无法正常渲染
  • lazy: true -- 次要数据、非首屏数据、可以先展示骨架屏的场景
// 核心数据 -- 阻塞导航等待数据(默认)
const { data: article } = await useApiFetch<Article>(`/articles/${id}`)

// 次要数据 -- 不阻塞导航,后台加载
const { data: related, status } = useLazyApiFetch<Article[]>(
  `/articles/${id}/related`
)
<template>
  <!-- 使用 lazy 时需要处理 loading 状态 -->
  <div v-if="status === 'pending'">
    <USkeleton class="h-20 w-full" />
  </div>
  <RelatedArticles v-else :articles="related" />
</template>
SSR 阶段 lazy 的行为与非 lazy 基本一致(都会等待数据返回),差异主要体现在客户端导航时。

immediate

控制是否在 composable 初始化时立即执行请求。默认 true

行为对比:

  • immediate: true(默认)-- 创建时立即触发请求
  • immediate: false -- 不自动请求,statusidle,需手动调用 execute() 触发

使用场景:

  • immediate: true -- 页面加载就需要的数据
  • immediate: false -- 需要等待用户操作后才触发的请求
// 预定义表单提交请求,不自动执行
const { data, execute, status, error } = useApiFetch('/login', {
  method: 'POST',
  body: credentials,
  immediate: false,
  lazy: true,
})

// 用户点击登录按钮时手动触发
async function handleLogin() {
  await execute()
  if (!error.value) {
    navigateTo('/dashboard')
  }
}
immediate: false 常与 lazy: true 搭配使用。如果只设 immediate: false 而不设 lazy: true,Suspense 仍会等待(虽然请求从未发出),可能导致页面悬挂。

Movk Nuxt API 系统

Movk Nuxt 提供基于 $fetch.create() 的 API 客户端工厂($api 插件),以及一组封装 useFetch 的 composable,在 Nuxt 原生数据获取能力之上提供统一的认证、业务检查、Toast 提示等增强功能。

nuxt.config.ts (movk.api 配置)
    |
    v
api.factory.ts 插件 -- 创建 $api 实例
    |
    v
拦截器链
├── onRequest:       认证注入 -> debug 日志 -> movk:api:request hook
├── onResponse:      业务检查 -> 数据解包 -> movk:api:response hook -> Toast
└── onResponseError: 401 处理 -> movk:api:error hook -> Toast
    |
    v
Composables
├── useApiFetch           useFetch + $api (SSR/CSR 通用)
├── useLazyApiFetch       lazy: true 预设
├── useClientApiFetch     server: false, lazy: true 预设
├── useUploadWithProgress XHR 上传 + 进度
└── useDownloadWithProgress fetch + ReadableStream 下载 + 进度

多端点支持

支持配置多个 API 端点,每个端点可独立设置 baseURL、认证、Toast 和响应规则。通过 endpoint 选项或 $api.use() 切换端点。

了解端点配置选项

自动认证

nuxt-auth-utils 集成。启用后,每次请求自动从 session 提取 token 并注入到请求头。支持嵌套路径(如 user.accessToken)和多种 token 格式(Bearer、Basic、Custom)。

了解认证配置选项

业务状态码检查

许多后端 API 返回统一格式的响应体:

// HTTP 200,但业务逻辑可能失败
{
  code: 400,           // 业务状态码
  message: '用户名已存在',
  data: null
}

$api 拦截器自动检查 code 是否在 successCodes(默认 [200, 0])中。业务失败时抛出 ApiError 并显示 Toast,无需手动处理。

了解响应配置选项

数据解包

$api 拦截器自动提取响应中 dataKey(默认 data)字段的值。useApiFetch<User>('/user') 中泛型 T 直接对应业务数据类型,无需手动 .data.value.data

// API 原始响应: { code: 200, message: 'OK', data: { id: 1, name: 'test' } }
const { data } = await useApiFetch<User>('/user')
// data.value = { id: 1, name: 'test' }  -- 自动解包

若响应中不存在 dataKey 字段,回退返回完整响应对象。

Toast 提示

请求成功/失败时自动显示 Toast 提示。支持四层配置优先级:请求级 > 端点级 > 全局级 > 内置默认值。可在任意层级禁用或自定义。

了解 Toast 配置选项

401 未授权处理

收到 HTTP 401 时,默认自动清除 session 并跳转登录页。可通过 API Hooks 拦截并实现自定义逻辑(如 token 刷新)。

了解 401 处理配置选项
Copyright © 2025 - 2026 YiXuan - MIT License