Nuxt 请求
Nuxt 请求分为 页面请求和 API请求
在 Nuxt.js 框架中,请求分为 页面请求(服务端渲染相关)和 API 请求(数据获取相关),两者在定位、执行时机和实现方式上有本质差异。以下是核心区别与实现逻辑的全面解析:
一、页面请求(服务端渲染流程)
定位:处理用户访问 URL 时触发的完整页面渲染流程,包含 SSR(服务端渲染)和客户端激活。
流程与关键阶段:
- 路由解析
- Nuxt 根据 URL 匹配路由规则,确定渲染的 Vue 组件(如
pages/user/[id].vue)。
- 数据预取
- 执行组件的
asyncData或setup中的useAsyncData/useFetch,在服务端获取初始数据:// 示例:页面级数据预取 export default defineComponent({ async asyncData({ params }) { const user = await $fetch(`/api/users/${params.id}`) return { user } } }) - 数据会序列化到 HTML 的
__NUXT_DATA__中,供客户端水合使用。
- HTML 生成与注入
- 服务端渲染 Vue 组件生成 HTML,注入序列化数据,返回给浏览器。
- 客户端激活
- 浏览器加载 HTML 后,Vue 接管 DOM,复用服务端数据激活交互逻辑,避免重复请求。
核心特点:
- SSR 优化:首屏由服务端渲染,提升 SEO 和加载性能。
- 数据同步:通过
useAsyncData确保数据在服务端和客户端一致性,避免水合不匹配(Hydration Mismatch)。
二、API 请求(数据获取)
定位:应用内部发起的数据调用,包括访问后端 API 或 Nuxt 自建的 Server API。
实现方式:
- 内置
$fetch方法
- 基于
ofetch库,全局自动导入,用于简单请求:// 客户端事件触发 async function submitForm() { const res = await $fetch('/api/submit', { method: 'POST', body: formData }) } - 局限:直接使用可能导致 SSR 重复请求。
- 组合式函数封装
useFetch:自动处理 SSR 重复请求,将服务端数据注入客户端 payload:const { data } = await useFetch('/api/data') // 服务端执行后数据同步到客户端useAsyncData:更精细控制,支持自定义键名缓存和刷新:const { data } = await useAsyncData('user-data', () => $fetch('/api/user')) 。
- Server API 开发
- Nuxt 自动注册
~/server/api目录下的文件为 API 端点:// ~/server/api/users/[id].ts export default defineEventHandler(event => { const id = getRouterParam(event, 'id') return { userId: id, name: 'Nuxt User' } }) - 支持动态路由、请求方法匹配(
get/post后缀)。
代理配置示例(解决跨域):
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
devProxy: {
'/api': { target: 'http://backend:3000', changeOrigin: true }
}
}
})
三、核心差异对比
| 维度 | 页面请求 | API 请求 |
|---|---|---|
| 触发时机 | 浏览器访问 URL 或路由跳转 | 代码显式调用(如事件、生命周期) |
| 主要技术 | asyncData, useAsyncData, useFetch | $fetch, Server API 端点 |
| 数据流 | 服务端获取 → 注入 HTML → 客户端水合 | 直接返回 JSON 或执行后端逻辑 |
| 典型场景 | 首屏渲染、SEO 页面 | 表单提交、实时数据更新 |
| 性能影响 | 优化首屏加载,减少客户端负担 | 需避免重复请求(SSR 下) |
四、最佳实践与避坑指南
- 页面请求优化
- 使用
useAsyncData替代asyncData(Nuxt 3 推荐)。 - 避免在页面请求中混合客户端逻辑,防止水合错误:
// 错误!客户端代码在服务端执行 if (process.client) { console.log('仅客户端输出') }
- API 请求封装
- 服务端专用请求:封装
useServerRequest,通过环境变量区分 baseURL:// composables/useServerRequest.ts export const useServerRequest = (url, opts) => { const baseURL = process.server ? 'http://service-url' : '/api' return useFetch(url, { ...opts, baseURL }) } 。 - 客户端事件请求:直接用
$fetch,减少序列化开销。
- 缓存与性能
- 利用
useAsyncData的key参数实现请求级缓存。 - 敏感数据避免通过 Server API 暴露(如
__NUXT_DATA__中的数据库凭证)。
总结
- 页面请求是 Nuxt 渲染生命周期的核心,通过 SSR 优化首屏体验,依赖
useAsyncData保证数据一致性。 - API 请求分为数据消费(
$fetch)和提供(Server API),需区分环境处理代理与序列化问题。 - 混合场景下,优先使用
useFetch封装通用请求逻辑,结合 Nitro 代理解决跨域,实现高效安全的数据流。