Skip to content

自动导入

Nuxt 的自动导入是其核心特性之一,让你无需手动写 import 语句就能使用组件、组合式函数和工具。

为什么自动导入很重要?

没有 Nuxt 自动导入时有 Nuxt 自动导入时
每个文件开头写 5-10 行 import不用写 import
忘了 import 就报错自动导入,不会忘
重命名组件要改所有 import改文件名就行,import 自动更新
代码中大量重复的 import 语句代码更简洁

自动导入的本质

Nuxt 在构建时扫描约定目录,自动为你生成 import 语句。你在代码中"直接用",Nuxt 帮你"补 import"。

INFO

注意:自动导入不是"魔法"——它只是帮你省略了 import 语句 代码运行时,import 仍然存在。如果你在 TypeScript 中看到类型报错,可能需要运行 nuxt prepare 重新生成类型声明

自动导入的目录

目录导入类型前缀规则典型内容
app/components/Vue 组件基于目录结构页面组件、UI 组件
app/composables/组合式函数use 前缀状态管理、数据逻辑
app/utils/工具函数无前缀格式化、计算、辅助函数
server/utils/服务端工具无前缀数据库、加密、服务端逻辑
shared/utils/共享工具无前缀前后端共用的纯函数

为什么 composables/ 要求 use 前缀?

这是 Vue 社区的命名约定:组合式函数以 use 开头(如 useCounteruseAuth)。Nuxt 借鉴了这个约定。虽然技术上不叫 useXxx 也能自动导入,但强烈建议遵守这个约定,代码可读性更好。

组件自动导入

app/components/ 下的 Vue 组件自动注册:

text
app/components/
├── AppHeader.vue           → <AppHeader>
├── AppFooter.vue           → <AppFooter>
├── Button.vue              → <Button>
├── Card/
│   ├── Card.vue            → <Card>
│   ├── CardHeader.vue      → <CardHeader>
│   └── CardBody.vue        → <CardBody>
└── user/
    ├── UserCard.vue         → <UserCard>
    └── UserAvatar.vue       → <UserAvatar>

在模板中直接使用:

vue
<template>
  <AppHeader />
  <UserCard :user="user" />
  <Card>
    <CardHeader>标题</CardHeader>
    <CardBody>内容</CardBody>
  </Card>
</template>

<!-- 不需要 import AppHeader from './components/AppHeader.vue' -->
<!-- 不需要 import UserCard from './components/user/UserCard.vue' -->
<!-- 等等... -->

以前用 Vue 是怎么做的?

vue
<script setup>
import AppHeader from './components/AppHeader.vue'
import UserCard from './components/user/UserCard.vue'
import Card from './components/Card/Card.vue'
import CardHeader from './components/Card/CardHeader.vue'
import CardBody from './components/Card/CardBody.vue'
</script>

Nuxt 帮你省掉了这些重复劳动。

懒加载组件

在组件名前加 Lazy 前缀即可懒加载:

vue
<template>
  <!-- 只有当 showHeavy 变为 true 时,HeavyComponent 才会被加载 -->
  <LazyHeavyComponent v-if="showHeavy" />
</template>

为什么要懒加载?

  • 有些组件体积很大(如地图、图表)
  • 有些组件初始时不需要显示(如弹窗、抽屉)
  • 懒加载将这些组件的代码单独打包,初始加载时不下载,需要时才加载
  • 有效减少首屏 JS 体积,加快首屏速度

什么时候用懒加载?

  • ❌ 导航栏、页脚——每个页面都要用,懒加载反而增加请求
  • ✅ 地图组件——体积大,只在特定页面用
  • ✅ 富文本编辑器——只在编辑页面用
  • ✅ 弹窗/对话框——用 v-if 控制时

组件命名规则

文件路径组件名规则说明
components/Button.vue<Button>文件名即组件名
components/BaseButton.vue<BaseButton>大驼峰命名
components/blog/PostCard.vue<BlogPostCard>目录名作为前缀
components/blog/post/Card.vue<BlogPostCard>多级目录,中间的 post 被忽略(因为同级有 PostCard

命名冲突怎么办?

text
components/
├── Button.vue              → <Button>
└── form/
└── Button.vue        → <FormButton>  ← 自动加目录名前缀

如果同级目录下有同名文件和目录,目录中的组件会有目录名前缀。但如果不确定,最好的做法是给组件起不同的名字,避免冲突。

最佳实践

  • 给组件加前缀区分用途:BaseButton(基础按钮)、AppHeader(应用头部)
  • 按功能分目录:form/card/table/
  • 避免和 UI 库组件重名(如 Element Plus 也有 Button

组合式函数自动导入

app/composables/ 下以 use 开头的函数自动导入:

ts
// app/composables/useCounter.ts
export const useCounter = (initial = 0) => {
  const count = useState('counter', () => initial)
  const increment = () => count.value++
  const decrement = () => count.value--
  return { count, increment, decrement }
}
vue
<script setup>
// 直接使用,无需 import
const { count, increment } = useCounter()
</script>

组合式函数的设计建议

  1. 单一职责:一个 composable 做一件事(如 useAuth 只管认证,useCounter 只管计数)
  2. 返回 ref 而不是普通值:确保响应式链不断裂
  3. 用 useState 而不是 ref:如果是跨组件共享的状态(SSR 安全)
  4. 接受参数而不是硬编码:如 useCounter(initial) 而不是 useCounter()
  5. 做好类型定义:返回值类型清晰,IDE 有提示

工具函数自动导入

app/utils/ 下的函数自动导入:

ts
// app/utils/formatDate.ts
export const formatDate = (date: string) => {
  return new Date(date).toLocaleDateString('zh-CN')
}
vue
<script setup>
// 直接使用,无需 import
const formatted = formatDate('2025-01-01')
</script>

composables/ vs utils/ 怎么选?

特征composables/utils/
命名use 前缀无特殊要求
是否响应式通常包含响应式数据通常不包含
是否有状态通常有通常无(纯函数)
典型例子useAuth()useCounter()formatDate()debounce()

简单判断

返回值包含 ref/computed?→ composables/;纯输入输出?→ utils/

Nuxt 内置自动导入

Nuxt 自动导入大量内置 API,无需手动 import:

组合式函数

ts
useFetch, useAsyncData, useState, useCookie, useRoute, useRouter,
useHead, useSeoMeta, useRuntimeConfig, useAppConfig, useNuxtApp,
useLazyFetch, useLazyAsyncData, ...

工具函数

ts
navigateTo, abortNavigation, createError, showError, clearError,
defineNuxtPlugin, definePageMeta, defineNuxtRouteMiddleware,
$fetch, callOnce, refreshNuxtData, ...

Vue API

ts
ref, reactive, computed, watch, watchEffect, onMounted, onUnmounted,
toRef, toRefs, nextTick, defineProps, defineEmits, ...

Vue 的 API 为什么也能自动导入?

Nuxt 配置了 vue@vue/runtime-core 的自动导入。所以你写 ref(0) 时,Nuxt 帮你补了 import { ref } from 'vue'

好处

代码更简洁,不用每个文件都写 import { ref, computed, onMounted } from 'vue'

自定义自动导入

从第三方库自动导入

ts
// nuxt.config.ts
export default defineNuxtConfig({
  imports: {
    presets: [
      {
        from: 'lodash-es',
        imports: ['debounce', 'throttle'],
      },
    ],
  },
})

什么时候需要?

如果你频繁使用某个库的函数(如 debounce),每次都写 import { debounce } from 'lodash-es' 很烦。配置后直接用 debounce() 就行。

INFO

注意:不要自动导入太多东西 否则 IDE 自动补全会很慢,而且可能出现命名冲突

扫描额外目录

ts
export default defineNuxtConfig({
  imports: {
    dirs: [
      'composables',              // 默认
      'composables/*/index.ts',   // 子目录
      'utils/**/*.ts',            // 工具函数
    ],
  },
})

禁用自动导入

ts
export default defineNuxtConfig({
  imports: {
    autoImport: false,  // 完全禁用
  },
})

INFO

不建议禁用 Nuxt 的很多特性(组合式函数、Vue API 等)都依赖自动导入。禁用后你需要手动 import 所有东西,失去了 Nuxt 最大的便利性

类型声明

自动导入的类型声明在 .nuxt/imports.d.ts 中自动生成。如果类型不正确,运行:

bash
npx nuxt prepare

为什么有时类型提示丢了?

  • 新建了 composable 但 IDE 不识别 → 需要重新生成类型
  • Git 切换分支后 → .nuxt/ 目录可能过时
  • npm install 后 → 运行 nuxt prepare 更新类型

注意事项

1. 避免命名冲突

ts
// ❌ 危险:和 VueUse 的 useFetch 重名
import { useFetch } from '@vueuse/core'

// ✅ 安全:Nuxt 的 useFetch 是自动导入的,不要从 VueUse 导入同名函数

如果必须用 VueUse 的 useFetch

给它起别名:

ts
import { useFetch as useVueUseFetch } from '@vueuse/core'

2. IDE 支持

确保安装了 Nuxt VS Code 插件(Nuxt - Nuxt DevTools),获得:

  • 自动补全
  • 类型提示
  • 跳转定义
  • 组件名高亮

3. 显式导入

如果需要,仍然可以手动 import,自动导入只是省略了这步:

ts
// 这两种写法都可以
const { data } = await useFetch('/api/users')          // 自动导入
const { data } = await import('#app').then(m => m.useFetch('/api/users'))  // 手动导入(不推荐)

4. 服务端代码隔离

server/utils/ 的自动导入仅在服务端生效,客户端代码无法使用:

ts
// server/utils/database.ts → 只能在 server/ 下使用
// app/pages/index.vue → 不能使用 server/utils/ 的函数

INFO

️ 这是 Nuxt 4 的类型隔离特性 如果你在客户端代码中用了 server/utils/ 的函数,TypeScript 会报错。如果前后端都要用,放在 shared/utils/

知识脉络

text
Nuxt 生命周期 → 你在这里:自动导入

                  ├─→ 相关:组合式函数 API 速查(13章)

                  ├─→ 相关:工具函数速查(15章)

                  └─→ 相关:内置组件速查(14章)

基于 Nuxt 4 官方文档整理编写