在 Nuxt.js(特别是 Nuxt 3) 中,composables/ 目录是一个约定目录,用于存放可复用的 组合式函数(Composables) 。这些函数基于 Vue 3 的 Composition API 编写,可以封装逻辑、状态、副作用等,并在组件或其他 composables 中复用。
✅ Composables 的使用原则
- 文件名通常以
use开头,如useCounter.ts。 - 每个 composable 应返回一个包含响应式数据、方法等的对象。
- 自动支持 自动导入(auto-imports) :无需手动 import,Nuxt 会自动从
composables/目录中导入。 - 支持 TypeScript(推荐使用
.ts后缀)。 - 在服务端(SSR)和客户端(CSR)都能安全运行(注意避免直接使用浏览器 API,如
window,需用onMounted或process.client判断)。
📁 项目结构示例
nuxt-project/
├── composables/
│ ├── useCounter.ts
│ └── useUser.ts
├── pages/
│ └── index.vue
├── nuxt.config.ts
└── package.json
🔧 示例 1:基础计数器(useCounter)
composables/useCounter.ts
import { ref, computed } from 'vue'
export const useCounter = () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
const increment = () => count.value++
const decrement = () => count.value--
const reset = () => (count.value = 0)
return {
count,
doubleCount,
increment,
decrement,
reset
}
}
💡 注意:即使没有显式 import,Nuxt 也会自动导入 useCounter。
🧪 在组件中使用
pages/index.vue
<template>
<div>
<h1>计数器示例</h1>
<p>当前值: {{ count }}</p>
<p>双倍值: {{ doubleCount }}</p>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<button @click="reset">重置</button>
</div>
</template>
<script setup>
// 无需 import!Nuxt 自动导入 useCounter
const { count, doubleCount, increment, decrement, reset } = useCounter()
</script>
🌐 示例 2:获取用户数据(useUser)
composables/useUser.ts
import { ref, onMounted } from 'vue'
export const useUser = () => {
const user = ref(null)
const loading = ref(true)
const error = ref(null)
const fetchUser = async () => {
try {
// 使用 $fetch(Nuxt 内置的 fetch 封装)
user.value = await $fetch('/api/user')
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
// 如果需要在客户端挂载后才获取(避免 SSR 问题),可用 onMounted
// 但 $fetch 在 SSR 下也能工作,所以这里直接调用也可以
if (process.server) {
// 可选:仅在服务端预取
fetchUser()
} else {
// 客户端也可触发
onMounted(fetchUser)
}
return {
user,
loading,
error,
fetchUser
}
}
⚠️ 注意:$fetch 是 Nuxt 提供的,支持 SSR/SSG,比原生 fetch 更强大。
📦 高级技巧
1. 命名空间与嵌套
你可以创建子目录:
composables/
└── auth/
└── useAuth.ts
使用时:
const { login } = useAuth()
Nuxt 会自动解析路径,无需更改导入方式。
2. 带参数的 Composable(工厂函数)
// composables/useTimer.ts
export const useTimer = (initial = 0) => {
const time = ref(initial)
const start = () => {
const interval = setInterval(() => time.value++, 1000)
onUnmounted(() => clearInterval(interval))
}
return { time, start }
}
使用:
const { time, start } = useTimer(10)
3. 避免重复实例(单例模式)
默认每次调用 useXXX() 都会创建新实例。若需共享状态(如全局用户信息),可结合 useState:
// composables/useGlobalUser.ts
export const useGlobalUser = () => {
const user = useState('user', () => null) // 跨组件共享
const setUser = (data) => user.value = data
return { user, setUser }
}
useState 是 Nuxt 提供的跨请求/组件的状态管理工具,支持 SSR。
✅ 最佳实践总结
| 建议 | 说明 |
|---|---|
使用 useXxx 命名 |
符合 Vue/Nuxt 约定 |
| 返回解构对象 | 方便按需使用 |
| 避免直接操作 DOM | 用 onMounted 包裹 |
优先用 $fetch |
而非原生 fetch |
共享状态用 useState |
避免多个组件状态不一致 |
📚 官方文档参考
- Nuxt 3 Composables
- Vue 3 Composition API