Chapter 07

Nuxt 3:全栈 Vue 框架

从零到全栈:Nuxt 3 的文件系统路由、自动导入、Server API 目录,让你用一套代码构建完整的 Web 应用

7.1 Nuxt 3 是什么?

Nuxt 3 是基于 Vue 3 的全栈框架,在 Vue 的基础上提供了:

# 使用官方脚手架
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run dev   # http://localhost:3000

7.2 项目目录结构

my-nuxt-app/
├── .nuxt/              # 自动生成,勿手动修改
├── assets/             # 需要构建工具处理的静态资源(图片、字体、CSS)
├── components/         # Vue 组件(自动导入)
│   ├── AppHeader.vue
│   └── ui/             # 子目录组件名:UiButton
│       └── Button.vue
├── composables/        # Composables(自动导入)
│   └── useCounter.ts
├── layouts/            # 布局组件
│   ├── default.vue     # 默认布局
│   └── auth.vue
├── middleware/         # 路由中间件
│   └── auth.ts
├── pages/              # 页面(自动生成路由)
│   ├── index.vue       # /
│   ├── about.vue       # /about
│   └── users/
│       ├── index.vue   # /users
│       └── [id].vue    # /users/:id(动态路由)
├── plugins/            # Nuxt 插件(在 Vue 实例创建前运行)
├── public/             # 直接提供的静态资源(无需构建)
├── server/             # 服务端代码(仅在服务器运行)
│   ├── api/
│   │   └── users.get.ts  # GET /api/users
│   ├── middleware/
│   └── utils/
├── utils/              # 工具函数(自动导入)
├── app.vue             # 应用根组件
├── nuxt.config.ts      # Nuxt 配置
└── package.json

7.3 文件系统路由

Nuxt 3 自动将 pages/ 目录下的 Vue 文件转换为路由,无需手动配置 Vue Router:

文件路径生成的路由说明
pages/index.vue/首页
pages/about.vue/about普通页面
pages/users/index.vue/users目录索引页
pages/users/[id].vue/users/:id动态路由
pages/users/[id]/posts.vue/users/:id/posts嵌套动态路由
pages/[...slug].vue/:slug(.*)*Catch-all(404 等)
pages/blog/[[page]].vue/blog 或 /blog/2可选参数
<script setup lang="ts">
// Nuxt 自动导入 useRoute,无需 import
const route = useRoute()
const id = route.params.id

// useFetch 也是自动导入的(Nuxt 内置)
const { data: user } = await useFetch(`/api/users/${id}`)

// 定义页面元信息(SEO)
useHead({
  title: () => user.value?.name ?? '用户详情',
  meta: [{ name: 'description', content: '用户个人主页' }]
})
</script>

7.4 自动导入(Auto-imports)

Nuxt 3 的一大特色是自动导入:无需手动 import,就可以直接使用以下内容:

Vue 核心 API
ref、reactive、computed、watch、watchEffect、onMounted 等,所有 Composition API 函数
Nuxt 内置
useFetch、useAsyncData、useHead、useRoute、useRouter、useState、useCookie、useNuxtApp 等
components/ 目录
所有 Vue 组件自动按需导入,子目录组件会添加前缀(ui/Button.vue → <UiButton>)
composables/ 目录
所有 composable 函数自动导入,支持嵌套目录
utils/ 目录
所有工具函数自动导入(注意:与 composables 不同,utils 不包含响应式逻辑)
自动导入的陷阱

自动导入仅在 .vue.tscomposables/utils/ 目录内)文件中生效。在 server/ 目录下不适用 Vue 相关的自动导入(因为服务端不运行 Vue)。如果 IDE 找不到类型,可以运行 npx nuxi prepare 生成类型文件。

7.5 Layouts 布局系统

<template>
  <div>
    <AppHeader />  <!-- 自动导入 -->
    <main>
      <slot />  <!-- 页面内容渲染到这里 -->
    </main>
    <AppFooter />
  </div>
</template>
<script setup>
// 指定使用 auth 布局(layouts/auth.vue)
definePageMeta({
  layout: 'auth'
})
</script>

7.6 Server API 路由

server/api/ 目录下的文件会自动成为 API 端点,基于 H3(轻量 HTTP 框架):

// GET /api/users
export default defineEventHandler(async (event) => {
  // 只在服务器运行,可以安全地访问数据库
  const db = useDatabase()
  const users = await db.query('SELECT * FROM users')
  return users  // 自动序列化为 JSON
})
// DELETE /api/users/:id
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')
  const body = await readBody<{ reason: string }>(event)

  // 验证身份(使用请求头)
  const token = getHeader(event, 'authorization')
  if (!token) throw createError({ statusCode: 401, message: '未授权' })

  await deleteUser(id)
  return { success: true }
})
文件名HTTP 方法URL
server/api/users.get.tsGET/api/users
server/api/users.post.tsPOST/api/users
server/api/users/[id].get.tsGET/api/users/:id
server/api/users/[id].delete.tsDELETE/api/users/:id
server/api/users/index.ts所有方法/api/users

7.7 nuxt.config.ts 配置

export default defineNuxtConfig({
  // 开发工具(开发环境自动启用 Vue DevTools)
  devtools: { enabled: true },

  // 模块(扩展 Nuxt 功能)
  modules: [
    '@nuxtjs/tailwindcss',
    '@pinia/nuxt',
    '@nuxt/image',
    'nuxt-auth-utils'
  ],

  // CSS 全局文件
  css: ['~/assets/css/main.css'],

  // 运行时配置(区分公开和私有)
  runtimeConfig: {
    // 私有:仅服务端可用
    dbUrl: process.env.DATABASE_URL,
    jwtSecret: process.env.JWT_SECRET,
    // 公开:客户端和服务端都可用
    public: {
      apiBase: '/api',
      appName: '我的应用'
    }
  },

  // TypeScript 配置
  typescript: {
    strict: true
  }
})
Nuxt 3 vs 纯 Vue 3 的选择

如果你的应用需要 SEO、快速首屏加载、或需要后端 API,选择 Nuxt 3。如果只是纯前端 SPA(如后台管理系统),选择 Vite + Vue 3 即可。Nuxt 3 在 SPA 项目中反而会增加不必要的复杂度。