2.1 核心目录与自动导入


2.1 核心目录与自动导入

上一章跑通了项目,本节把镜头拉近到目录层:Nuxt 的每个保留目录都对应一类自动行为,理解这套映射,就理解了"约定优于配置"的实现方式。本节是第 4、5、6 章的公共地基——composables、middleware、server 三个目录的深度用法都从这里的规则出发。

八个保留目录各自管什么

先上全景图,再逐个说细节。

图 2-1:Nuxt 目录约定全景

图 2-1:Nuxt 目录约定全景

几个容易混淆的点单独强调:

pages 是路由的总开关。项目里没有 pages 目录时,Nuxt 不启用文件路由,app.vue 就是整个应用;一旦创建 pages 目录并放入第一个页面,路由系统自动激活。这个"从无到有"的切换常让新手困惑:明明加了页面组件,访问路径却 404——通常是目录名拼错或文件没放对位置。

components 的命名规则components/base/Button.vue 注册为 BaseButton(目录并入前缀);若目录下有 base/Button.vuebase/BaseButton.vue,默认后者优先后缀拼接会得到 BaseButton——遇到重名,用配置里的 pathPrefix 显式控制,别靠猜。

plugins 的执行时机。文件在应用启动时自动运行一次,适合给整个应用注入能力(比如注册一个全局指令、初始化一个图表库)。插件本质是"带 nuxtApp 上下文的安装函数",第 7 章写模块时会看到同样的机制。

自动导入的作用域与开关

自动导入(Auto Imports)是上面所有"自动"的底层机制:Nuxt 在构建期扫描约定目录,把导出项注册进一个虚拟模块,代码里直接使用即可。作用域分三层:

层级 覆盖范围 典型成员
Vue 与 Nuxt 内置 全项目,服务端与客户端都可用 ref、computed、watch、useRoute、useFetch
composables 导出 全项目自动导入 自写的 useXxx 函数
components 导出 全项目模板中自动注册 任意 .vue 组件

自写一个组合函数验证。在 composables 目录新建文件:

// composables/useNow.ts // 约定目录内的导出,无需任何注册即可全局使用 export const useNow = () => useState<Date>('now', () => new Date())

随后任意组件中直接调用 useNow(),不需要 import。这里埋个伏笔:useState 是 Nuxt 提供的跨端状态容器,它能保证服务端设置的值在客户端水合时不丢——这正是第 4 章的主题。

自动导入虽好,边界要清楚:

  • 只有约定目录顶层或 index 文件的导出保证被扫描,深层的具名导出依赖目录扫描策略,团队约定最好统一放顶层;
  • 第三方库不会被自动导入,import 照常写;
  • 想显式管理,可以在配置里整体关闭:
// nuxt.config.ts export default defineNuxtConfig({ imports: { autoImport: false }, // 关闭 API 自动导入 components: { dirs: [] }, // 关闭组件自动注册 })

从一个真实目录树读项目

八个目录拼起来,一个中型电商项目的目录树长这样。拿到陌生项目时,照这张表逐目录扫描,五分钟内能判断出它的功能边界:

relay-shop/ ├── app.vue # 全局壳:NuxtLayout 包 NuxtPage ├── nuxt.config.ts # 五层配置(2.2) ├── error.vue # 兜底错误页(2.3) ├── assets/css/main.css # 参与构建的全局样式 ├── public/favicon.ico # 原样拷贝的固定路径资源 ├── components/ │ ├── ProductCard.vue # 全局注册为 ProductCard │ └── base/Button.vue # 注册为 BaseButton ├── composables/ │ ├── useProducts.ts # 商品数据层(4.3) │ └── useAuth.ts # 会话三件套(5.2) ├── layouts/ │ ├── default.vue # 导航加页脚 │ └── bare.vue # 结账极简布局 ├── middleware/ │ └── auth.global.ts # 全站登录守卫 ├── pages/ │ ├── index.vue # / │ └── products/[id].vue # /products/:id ├── plugins/ │ └── error-observer.client.ts # 生产错误哨位(9.2) └── server/ ├── api/products/[id].get.ts # GET /api/products/:id └── middleware/1.logger.ts # 请求日志(6.2)

读树的三个锚点:先看 pages 的层级(路由结构即信息架构),再看 server/api 的文件名(自带哪些后端能力),最后扫 middleware 与 plugins(行为约束与全局注入)。这三个锚点定下来,其余目录都是支撑角色。

自动导入的显式化策略

自动导入用久了会冒出新问题:"这个函数是哪来的?" newcomers 对满屏无 import 的代码束手无策,IDE 的跳转有时也失灵。三个治理手段:

手段一:统一命名前缀。自写的组合函数强制 use 业务前缀(useOrderFetch 而非 useFetch2),看到前缀就知道来自 composables 目录;组件同理用目录前缀分层。

手段二:入口文档化。在项目 README 或约定文件里列一份"自动可用清单"——内置 API 常用项、自写组合函数、组件命名规则。新人入职第一份读物就是它。

手段三:局部显式。关键文件(比如被多处复用的工具函数)保留显式 import,用注释说明"此处显式引入是为可读性"。自动导入是权限不是义务,团队觉得显式更清晰的区域可以自主收紧。

这三种手段的共同思想:自动导入降低的是打字成本,不该抬高理解成本。约定目录的"物理位置即语义"本身就是文档——文件在 composables 里,读者自然知道它是可复用逻辑;这比注释"此函数可复用"可靠得多。

⚠️ 常见坑:命名冲突。自写的 useFetch 会与内置同名 API 竞争,行为取决于扫描顺序。组合函数一律用业务前缀命名(如 useOrderFetch),从源头避免。

💡 关键直觉:自动导入省掉的是注册而非声明——文件还是要建、还是要导出,只是"在哪里登记"这一步框架代劳了。理解这点,魔法就还原成了机制。

本节要点回顾

  • 八目录职责:pages 路由、components 注册、composables 导入、layouts 模板、middleware 拦截、server 服务端、plugins 注入、public 原样拷贝;
  • pages 是路由开关:目录存在与否决定文件路由是否激活;
  • components 命名:子目录并入前缀,重名冲突用配置显式裁决;
  • 自动导入三层:内置 API、composables 导出、components 注册,第三方库不在此列;
  • public 与 assets 分工:固定路径进 public,参与构建优化进 assets;
  • 可整体关闭:imports 与 components 配置项提供了退出自动导入的开关,满足显式偏好。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U