Nuxt 3 插件系统与自动导入
Nuxt 3 的插件系统和自动导入功能可以显著提升开发效率。本文深度讲解这两个核心功能。
1. 插件系统基础
什么是插件
插件是在应用启动前执行的代码,用于:
├─ 全局注册组件、指令、方法
├─ 集成第三方库
├─ 初始化应用状态
├─ 监听全局事件
└─ 扩展 Vue 应用能力
创建基础插件
// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
console.log('插件加载中...')
// 返回插件提供的内容
return {
provide: {
// 全局方法
myMethod: () => 'Hello World',
// 全局属性
version: '1.0.0'
}
}
})
// 在组件中使用
export default {
setup() {
const { $myMethod, $version } = useNuxtApp()
console.log($myMethod()) // "Hello World"
console.log($version) // "1.0.0"
}
}
2. 常用插件模式
模式 1: 全局状态管理
// plugins/init-store.ts
export default defineNuxtPlugin(() => {
const authStore = useAuthStore()
const settingsStore = useSettingsStore()
// 应用启动时初始化
return {
provide: {
stores: {
auth: authStore,
settings: settingsStore
}
}
}
})
模式 2: API 客户端
// plugins/api-client.ts
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin((nuxtApp) => {
// 创建 API 客户端
const apiClient = {
async get(url: string, options?: any) {
return $fetch(url, options)
},
async post(url: string, data: any, options?: any) {
return $fetch(url, {
method: 'POST',
body: data,
...options
})
}
}
return {
provide: {
api: apiClient
}
}
})
// 使用
const { $api } = useNuxtApp()
const data = await $api.get('/api/users')
模式 3: 全局指令
// plugins/directives.ts
export default defineNuxtPlugin((nuxtApp) => {
// v-focus 指令: 自动聚焦输入框
nuxtApp.vueApp.directive('focus', {
mounted(el: HTMLElement) {
el.focus()
}
})
// v-click-outside 指令
nuxtApp.vueApp.directive('click-outside', {
mounted(el: HTMLElement, binding) {
el.clickOutsideEvent = (event: Event) => {
if (!(el as any).contains(event.target)) {
binding.value(event)
}
}
document.addEventListener('click', (el as any).clickOutsideEvent)
},
unmounted(el: HTMLElement) {
document.removeEventListener('click', (el as any).clickOutsideEvent)
}
})
})
// 使用
<template>
<input v-focus />
<div v-click-outside="closeMenu">...</div>
</template>
模式 4: 第三方库集成
// plugins/vue-toast.ts
import VueToast from 'vue-toast-notification'
import 'vue-toast-notification/dist/theme-default.css'
export default defineNuxtPlugin((nuxtApp) => {
// 注册第三方组件库
nuxtApp.vueApp.use(VueToast)
// 也可以只注册全局方法
const $toast = (message: string, options?: any) => {
// 自定义 toast 实现
console.log(message)
}
return {
provide: {
toast: $toast
}
}
})
// 使用
const { $toast } = useNuxtApp()
$toast('操作成功!')
模式 5: 拦截器
// plugins/request-interceptor.ts
export default defineNuxtPlugin((nuxtApp) => {
const interceptors = {
request: [],
response: [],
error: []
}
// 注册请求拦截器
const addRequestInterceptor = (handler: (config: any) => any) => {
interceptors.request.push(handler)
}
// 注册响应拦截器
const addResponseInterceptor = (handler: (response: any) => any) => {
interceptors.response.push(handler)
}
// 注册错误拦截器
const addErrorInterceptor = (handler: (error: any) => any) => {
interceptors.error.push(handler)
}
return {
provide: {
interceptors,
addRequestInterceptor,
addResponseInterceptor,
addErrorInterceptor
}
}
})
3. 自动导入 (Auto-imports)
什么是自动导入
自动导入解决的问题:
├─ 无需手动 import 常用的 composables
├─ 无需手动 import 常用的工具函数
├─ 无需手动 import Nuxt 提供的方法
└─ 减少代码重复
例子:
// ❌ 手动导入 (繁琐)
import { useState, useRouter, useRoute } from 'vue'
import { useAsyncData, useRouter } from '#app'
import { useAuthStore } from '~/stores/auth'
// ✅ 自动导入 (简洁)
// 直接使用,无需导入!
const count = useState('count', () => 0)
const router = useRouter()
const authStore = useAuthStore()
配置自动导入
// nuxt.config.ts
export default defineNuxtConfig({
imports: {
// 自动导入特定的 composable
dirs: [
'composables',
'composables/**/index.ts'
]
},
// 自动导入 @vueuse/core 中的所有方法
modules: [
['@vueuse/nuxt', {
// useWindowSize 等方法会自动导入
}]
]
})
自动导入的内容
// ✅ Nuxt 自动导入的全局方法
// Vue 3
- ref, reactive, computed, watch
- onMounted, onUnmounted, onUpdated
- useSlots, useAttrs, useAsyncData
// Nuxt 3
- useRouter, useRoute, useHead
- useFetch, useAsyncData, useLazyAsyncData
- navigateTo, definePageMeta, defineRouteRules
- useState, useCookie, useRequestHeaders
// 你的 composables/
- useCounter (自动从 composables/useCounter.ts)
- useAuthStore (自动从 composables/useAuthStore.ts)
创建可自动导入的 Composable
// composables/useCounter.ts
export const useCounter = () => {
const count = useState('count', () => 0)
const increment = () => count.value++
const decrement = () => count.value--
return {
count,
increment,
decrement
}
}
// 在任何组件中直接使用,无需导入!
<script setup lang="ts">
const { count, increment } = useCounter()
</script>
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">增加</button>
</div>
</template>
组织自动导入
composables/
├── useCounter.ts → 自动导入为 useCounter
├── useAuth/
│ └── index.ts → 自动导入为 useAuth
├── useAuth/
│ ├── useLogin.ts → 自动导入为 useLogin (或 useAuthUseLogin)
│ └── useLogout.ts → 自动导入为 useLogout
└── api/
├── useUsers.ts → 自动导入为 useUsers
└── useProducts.ts → 自动导入为 useProducts
4. 自动导入组件
组件自动注册
components/
├── Button.vue → 自动注册为 <Button />
├── Card.vue → 自动注册为 <Card />
│
├── UI/
│ ├── Input.vue → 自动注册为 <UIInput />
│ └── Modal.vue → 自动注册为 <UIModal />
│
└── Form/
├── Input.vue → 自动注册为 <FormInput />
└── Select.vue → 自动注册为 <FormSelect />
<!-- ✅ 直接使用,无需导入 -->
<template>
<div>
<Button>点击</Button>
<UIInput placeholder="输入..." />
<FormSelect :options="options" />
</div>
</template>
配置组件导入
// nuxt.config.ts
export default defineNuxtConfig({
components: {
// 仅自动注册特定目录的组件
dirs: [
'~/components',
{
path: '~/components/ui',
prefix: 'UI' // UI 前缀
}
]
}
})
5. 自动导入工具函数
创建工具库
// utils/helpers.ts
export const formatDate = (date: Date) => {
return new Intl.DateTimeFormat('zh-CN').format(date)
}
export const formatCurrency = (amount: number) => {
return new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY'
}).format(amount)
}
export const debounce = (func: Function, delay: number) => {
let timer: any
return (...args: any[]) => {
clearTimeout(timer)
timer = setTimeout(() => func(...args), delay)
}
}
// 在任何组件中直接使用
<script setup lang="ts">
const dateStr = formatDate(new Date())
const price = formatCurrency(99.99)
</script>
6. 插件和自动导入最佳实践
// ✅ 最佳实践
// 1. 命名约定
// ✅ 插件: plugins/[name].ts
// ✅ Composable: composables/use[Name].ts
// ✅ 组件: components/[Name].vue
// ✅ 工具: utils/[name].ts
// 2. 组织结构
composables/
├── useAuth.ts (认证相关)
├── useData.ts (数据获取)
└── useSocial/
├── index.ts
├── useTwitter.ts
└── useWeibo.ts
// 3. 避免命名冲突
// ✅ 好: 明确的前缀
useAuthStore
useDataFetch
useUIModal
// ❌ 避免: 模糊的名称
useStore (哪个 store?)
useFetch (什么数据?)
// 4. 按需加载
// ✅ 好: 只在需要时加载
plugins: [
{ src: '~/plugins/google-analytics.ts', mode: 'client' }
]
// ❌ 避免: 加载所有插件
plugins: ['~/plugins/*.ts']
7. 性能考虑
// 插件加载策略
// 1. 条件加载
export default defineNuxtPlugin((nuxtApp) => {
// 仅在浏览器中加载
if (process.server) return
// 初始化客户端功能
})
// 2. 懒加载
export default defineNuxtPlugin(async (nuxtApp) => {
// 异步加载,不阻塞应用初始化
const module = await import('~/libs/heavy-library')
return {
provide: {
heavyLib: module
}
}
})
// 3. 条件导入
if (process.env.NODE_ENV === 'development') {
// 仅开发环境加载调试工具
}
总结
Nuxt 3 的插件和自动导入系统的核心优势:
| 特性 | 优势 |
|---|---|
| 插件系统 | 灵活扩展应用能力 |
| 自动导入 | 减少代码重复 |
| 组件自动注册 | 提升开发效率 |
| 类型安全 | TypeScript 完整支持 |
| 按需加载 | 优化性能 |


