目录结构✅
本主题涵盖 Nuxt 项目的目录结构约定,包括各个目录的作用、文件命名规范和组织方式。
Nuxt 项目的标准目录结构是什么样的?
答案
核心概念
Nuxt 采用约定优于配置的理念,通过标准化的目录结构来组织项目,减少配置复杂度,提高开发效率。
标准目录结构
nuxt-project/
├── .nuxt/ # Nuxt 构建输出目录(自动生成)
├── .output/ # 生产构建输出目录
├── assets/ # 需要构建处理的静态资源
├── components/ # Vue 组件(自动导入)
├── composables/ # 组合式函数(自动导入)
├── layouts/ # 布局组件
├── middleware/ # 路由中间件
├── pages/ # 页面组件(自动生成路由)
├── plugins/ # 插件
├── public/ # 静态资源(直接访问)
├── server/ # 服务端代码
│ ├── api/ # API 路由
│ ├── middleware/ # 服务端中间件
│ └── plugins/ # 服务端插件
├── stores/ # 状态管理(Pinia)
├── types/ # TypeScript 类型定义
├── utils/ # 工具函数(自动导入)
├── app.vue # 根组件
├── nuxt.config.ts # Nuxt 配置文件
├── package.json # 项目依赖
└── tailwind.config.js # Tailwind 配置(如果使用)
关键目录说明
-
pages/ - 页面路由
- 每个
.vue
文件自动生成一个路由 - 支持嵌套路由和动态路由
- 每个
-
components/ - 组件库
- 所有组件自动导入,无需手动 import
- 支持嵌套目录结构
-
layouts/ - 布局模板
- 定义页面的整体布局结构
- 页面可以选择使用不同的布局
-
server/api/ - API 路由
- 服务端 API 接口
- 支持 RESTful 和 GraphQL
-
middleware/ - 路由中间件
- 在页面渲染前执行
- 用于权限验证、重定向等
示例说明
<!-- pages/index.vue - 首页 -->
<template>
<div>
<h1>欢迎来到 Nuxt 应用</h1>
<UserCard :user="user" />
</div>
</template>
<script setup>
// components/UserCard.vue 自动导入,无需 import
const { data: user } = await $fetch('/api/user')
</script>
<!-- layouts/default.vue - 默认布局 -->
<template>
<div class="layout">
<header>
<nav>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
</nav>
</header>
<main>
<slot />
</main>
<footer>
<p>© 2024 My App</p>
</footer>
</div>
</template>
面试官视角
该题考察候选人对 Nuxt 约定优于配置理念的理解,是 Nuxt 开发的基础知识。通过此题可以引出自动导入、路由生成等更深层的概念。
延伸阅读
pages 目录如何自动生成路由?
答案
核心概念
Nuxt 基于文件系统的路由,pages 目录中的每个 .vue
文件都会自动生成对应的路由,无需手动配置路由表。
路由生成规则
-
基础路由
pages/index.vue → /
pages/about.vue → /about
pages/contact.vue → /contact -
嵌套路由
pages/
├── index.vue → /
├── about.vue → /about
└── products/
├── index.vue → /products
└── detail.vue → /products/detail -
动态路由
pages/users/[id].vue → /users/:id
pages/posts/[slug].vue → /posts/:slug -
嵌套动态路由
pages/users/[id]/
├── index.vue → /users/:id
├── edit.vue → /users/:id/edit
└── settings.vue → /users/:id/settings
实际示例
<!-- pages/users/[id].vue -->
<template>
<div>
<h1>用户详情</h1>
<p>用户ID: {{ $route.params.id }}</p>
<UserProfile :userId="$route.params.id" />
</div>
</template>
<script setup>
// 获取路由参数
const route = useRoute()
const userId = route.params.id
// 获取查询参数
const query = route.query
</script>
<!-- pages/blog/[...slug].vue - 捕获所有路由 -->
<template>
<div>
<h1>博客文章</h1>
<p>路径: {{ $route.params.slug.join('/') }}</p>
</div>
</template>
<script setup>
const route = useRoute()
// slug 是一个数组,包含所有路径段
const slug = route.params.slug
</script>
特殊文件
- index.vue - 目录的默认页面
- [...slug].vue - 捕获所有路由
- [...].vue - 捕获所有路由(包括空路径)
路由导航
<template>
<div>
<!-- 使用 NuxtLink 组件 -->
<NuxtLink to="/users/123">用户详情</NuxtLink>
<!-- 编程式导航 -->
<button @click="navigateToUser">跳转到用户页面</button>
</div>
</template>
<script setup>
const router = useRouter()
const navigateToUser = () => {
router.push('/users/123')
// 或者使用 navigateTo
await navigateTo('/users/123')
}
</script>
面试官视角
该题考察候选人对 Nuxt 文件系统路由的理解,是 Nuxt 开发的核心概念。通过此题可以引出动态路由、嵌套路由等更复杂的路由场景。
延伸阅读
layouts 目录的作用和使用方式?
答案
核心概念
Layouts 是 Nuxt 中用于定义页面整体布局结构的组件,允许在不同页面间共享相同的布局,提高代码复用性。
布局系统特点
- 自动应用:页面会自动使用默认布局
- 灵活切换:页面可以指定使用不同的布局
- 嵌套支持:布局可以嵌套使用
- 响应式:布局可以响应式适配不同设备
标准布局结构
<!-- layouts/default.vue - 默认布局 -->
<template>
<div class="default-layout">
<header class="header">
<nav class="nav">
<NuxtLink to="/" class="nav-link">首页</NuxtLink>
<NuxtLink to="/about" class="nav-link">关于</NuxtLink>
<NuxtLink to="/contact" class="nav-link">联系</NuxtLink>
</nav>
</header>
<main class="main">
<slot />
</main>
<footer class="footer">
<p>© 2024 My App</p>
</footer>
</div>
</template>
<style scoped>
.default-layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
padding: 2rem;
}
</style>
自定义布局
<!-- layouts/admin.vue - 管理后台布局 -->
<template>
<div class="admin-layout">
<aside class="sidebar">
<nav class="admin-nav">
<NuxtLink to="/admin/dashboard">仪表盘</NuxtLink>
<NuxtLink to="/admin/users">用户管理</NuxtLink>
<NuxtLink to="/admin/settings">系统设置</NuxtLink>
</nav>
</aside>
<main class="admin-main">
<header class="admin-header">
<h1>管理后台</h1>
<UserMenu />
</header>
<div class="admin-content">
<slot />
</div>
</main>
</div>
</template>
<style scoped>
.admin-layout {
display: flex;
min-height: 100vh;
}
.sidebar {
width: 250px;
background: #f5f5f5;
padding: 1rem;
}
.admin-main {
flex: 1;
display: flex;
flex-direction: column;
}
.admin-content {
flex: 1;
padding: 2rem;
}
</style>
页面使用布局
<!-- pages/about.vue - 使用默认布局 -->
<template>
<div>
<h1>关于我们</h1>
<p>这是关于页面,使用默认布局</p>
</div>
</template>
<!-- pages/admin/dashboard.vue - 使用自定义布局 -->
<template>
<div>
<h1>管理仪表盘</h1>
<div class="stats">
<div class="stat-card">总用户数: 1000</div>
<div class="stat-card">今日访问: 500</div>
</div>
</div>
</template>
<script setup>
// 指定使用 admin 布局
definePageMeta({
layout: 'admin'
})
</script>
布局切换
<!-- 动态切换布局 -->
<template>
<div>
<button @click="toggleLayout">切换布局</button>
<p>当前布局: {{ currentLayout }}</p>
</div>
</template>
<script setup>
const currentLayout = ref('default')
const toggleLayout = () => {
currentLayout.value = currentLayout.value === 'default' ? 'admin' : 'default'
setPageLayout(currentLayout.value)
}
</script>
布局错误处理
<!-- layouts/error.vue - 错误页面布局 -->
<template>
<div class="error-layout">
<div class="error-content">
<h1>{{ error.statusCode }}</h1>
<p>{{ error.statusMessage }}</p>
<NuxtLink to="/">返回首页</NuxtLink>
</div>
</div>
</template>
<script setup>
const props = defineProps({
error: Object
})
</script>
面试官视角
该题考察候选人对 Nuxt 布局系统的理解,是构建复杂应用的重要概念。通过此题可以引出页面元数据、错误处理等更深层的功能。
延伸阅读