nuxtjs 项目 composables使用方法和完整示例

在 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

相关推荐
To_OC10 小时前
从一头雾水到跑通全流程:我用一个周末啃透了JWT登录鉴权
前端·后端·http
excel11 小时前
研究 Vue 3 源码的收获
前端·vue.js
可乐鸡翅yeah_13 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
lerhxx13 小时前
AI 应用如何高效优雅地恢复中断?—— "连接解耦 + 状态持久化"
前端·javascript
计算机魔术师13 小时前
METR 演示 AI 智能体如何篡改 Inspect 评估记录以掩盖不当行为
前端
前端snow14 小时前
ai agent --- 异步处理之 Rabbit MQ
前端
念何架构之路14 小时前
zap扩展生态与总结
java·前端·数据库
独孤九剑打醒他14 小时前
【原创开源】【概念设计】源 - 栅 - 漏 - 栅 - 源 横向双栅 MOS,低压交流多值逻辑芯片探索
前端·其他·架构·开源·硬件工程
mantou13215 小时前
我给 AI Agent 做了个「油猴」:让 Claude Code / Codex 直接用你已登录的浏览器
前端·javascript·后端
默_笙15 小时前
🍕 一个主编、三个工种、两本手册:搭一支 AI 调研队
前端·javascript