mcpField
P
pinia-colada

pinia-colada

github.com/secondsky开发240243 次安装5 周前更新
代码仓库

关于 pinia-colada

pinia-colada 是面向 Vue 3 和 Nuxt 开发者的 Pinia 数据获取技能,提供查询、缓存与变更的实现指导。它还整理了常见错误、SSR 设置和可复用模式。

主要功能

  1. 01查询与响应式缓存
  2. 02变更及查询失效
  3. 03乐观更新与回滚
  4. 04分页、轮询和预取模式
  5. 05Nuxt SSR 配置指导
  6. 06错误排查参考

适用场景

  1. 01为待办列表实现 CRUD 数据流
  2. 02构建带占位数据的分页表格
  3. 03为变更操作添加乐观更新
  4. 04在 Nuxt 应用中配置 SSR 数据获取

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill pinia-colada

安装后在 Claude Code 中输入/pinia-colada确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
common-patterns.md
configuration.md
error-catalog.md
migration-from-tanstack-vue-query.md
setup-guide.md

详细介绍

Pinia Colada——为 Vue 提供智能数据获取

状态:已可用于生产环境 ✅ | 上次更新:2025-11-28 最新版本:@pinia/[email protected] | 依赖项:Vue 3.5.17+、Pinia 2.2.6+ 或 3.0+


快速入门(5 分钟)

1. 安装依赖

适用于 Vue 项目:

bun add @pinia/colada pinia  # preferred
# or: bun add @pinia/colada pinia

适用于 Nuxt 项目:

bun add @pinia/nuxt @pinia/colada-nuxt  # install both Pinia and Pinia Colada modules
# or: bun add @pinia/nuxt @pinia/colada-nuxt

原因:

  • Pinia Colada 需要 Pinia 2.2.6+ 或 3.0+ 作为对等依赖
  • Nuxt 模块会自动处理 SSR 序列化
  • 为获得最佳响应性,需要 Vue 3.5.17+
2. 设置 Pinia Colada 插件

适用于 Vue 项目:

// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { PiniaColada } from '@pinia/colada'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia()

app.use(pinia)
app.use(PiniaColada, {
  // Optional: Configure defaults
  query: {
    staleTime: 5000,        // 5 seconds
    gcTime: 5 * 60 * 1000,  // 5 minutes (garbage collection)
    refetchOnMount: true,
    refetchOnWindowFocus: false,
  },
})

app.mount('#app')

适用于 Nuxt 项目:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@pinia/nuxt',           // Must be before @pinia/colada-nuxt
    '@pinia/colada-nuxt',
  ],

  // Optional: Configure Pinia Colada
  piniaColada: {
    query: {
      staleTime: 5000,
      gcTime: 5 * 60 * 1000,
    },
  },
})

重要:

  • 对于 Nuxt:@pinia/nuxt 必须列在 @pinia/colada-nuxt 之前
  • 必须在 Pinia 实例之后注册插件
  • 配置是可选的——已提供合理的默认值
3. 创建第一个查询
<script setup lang="ts">
import { useQuery } from '@pinia/colada'

interface Todo {
  id: number
  title: string
  completed: boolean
}

async function fetchTodos(): Promise<Todo[]> {
  const response = await fetch('/api/todos')
  if (!response.ok) {
    throw new Error('Failed to fetch todos')
  }
  return response.json()
}

const {
  data,       // Ref<Todo[] | undefined>
  isPending,  // Ref<boolean> - initial loading
  isLoading,  // Ref<boolean> - any loading (including refetch)
  error,      // Ref<Error | null>
  refresh,    // () => Promise<void> - manual refetch
} = useQuery({
  key: ['todos'],
  query: fetchTodos,
})
</script>

<template>
  <div>
    <div v-if="isPending">Loading todos...</div>
    <div v-else-if="error">Error: {{ error.message }}</div>
    <ul v-else-if="data">
      <li v-for="todo in data" :key="todo.id">
        {{ todo.title }}
      </li>
    </ul>
  </div>
</template>

重要:

  • 查询 key 必须是数组(或返回数组的 getter),以确保缓存一致
  • 查询 query 是用于获取数据的异步函数
  • 在查询函数中抛出错误,以便正确处理错误
  • isPending 仅在初次加载时为 true,isLoading 则包含重新获取数据的情况
4. 创建第一个变更
<script setup lang="ts">
import { useMutation, useQueryCache } from '@pinia/colada'

interface NewTodo {
  title: string
}

async function createTodo(newTodo: NewTodo) {
  const response = await fetch('/api/todos', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newTodo),
  })
  if (!response.ok) throw new Error('Failed to create todo')
  return response.json()
}

const queryCache = useQueryCache()

const {
  mutate,        // (variables: NewTodo) => Promise<void>
  mutateAsync,   // (variables: NewTodo) => Promise<Result>
  isPending,     // Ref<boolean>
  error,         // Ref<Error | null>
  data,          // Ref<Result | undefined>
} = useMutation({
  mutation: createTodo,

  // Invalidate todos query after mutation succeeds
  async onSettled({ id }) {
    await queryCache.invalidateQueries({ key: ['todos'] })
  },
})

function handleAddTodo(title: string) {
  mutate({ title })
}
</script>

<template>
  <form @submit.prevent="handleAddTodo(newTitle)">
    <input v-model="newTitle" required />
    <button type="submit" :disabled="isPending">
      {{ isPending ? 'Adding...' : 'Add Todo' }}
    </button>
    <div v-if="error">Error: {{ error.message }}</div>
  </form>
</template>

这样做的原因:

  • onSettled 会在成功或出错后运行,非常适合用于失效处理
  • invalidateQueries 会将匹配的查询标记为过期,并重新获取活跃查询的数据
  • mutate 会触发操作但不等待结果,mutateAsync 会返回 Promise,供 await 使用
  • 默认情况下,变更不会缓存(这是写入操作的正确行为)

关键规则

务必做到

✅ 将查询函数中使用的所有变量都包含在 key 中 ✅ 在查询/变更函数中抛出错误,以便正确处理错误 ✅ 在变更操作中使用 useQueryCache() 进行失效处理 ✅ 初次加载时使用 isPending,任何加载状态都使用 isLoading ✅ 需要在继续之前确保数据为最新时,在 onSettled 中等待 invalidateQueries() ✅ 对分页查询使用 placeholderData,以避免界面闪烁 ✅ 在乐观更新前使用 getQueryData 快照缓存 ✅ 从 onMutate 返回上下文,以便在 onError 中回滚 ✅ 在插件级别配置 staleTime 和 gcTime,作为整个应用的默认值 ✅ 使用可复用的组合式函数封装查询,而不是内联使用 useQuery

切勿这样做

❌ 切勿使用普通字符串作为 key——始终使用数组 ❌ 切勿从查询函数返回 undefined——应改为抛出错误 ❌ 切勿直接修改 data.value——它是只读的 ❌ 变更后切勿忘记使相关查询失效 ❌ 切勿在查询中使用 onSuccess(不可用,应改用 watch) ❌ 切勿忘记等待 mutateAsync()——它会返回 Promise ❌ 乐观更新前切勿跳过 cancelQueries(这会导致竞态条件) ❌ 使用 getQueryData 时切勿不检查其是否为 undefined ❌ 切勿在 onMutate 中使查询失效(应在 onSettled 中执行) ❌ 切勿硬编码 URL——使用环境变量设置 API 基础 URL


预防最常见的 5 个错误

此技能可预防 12 个已记录的错误。以下是最常见的 5 个:

错误 #1:变更后查询未重新获取数据

错误:变更成功后,界面中的数据没有更新 预防方法:始终在 onSettled 中使用 invalidateQueries:

useMutation({
  mutation: createTodo,
  async onSettled() {
    await queryCache.invalidateQueries({ key: ['todos'] })
  },
})

参见:references/error-catalog.md #1

错误 #2:乐观更新中的竞态条件

错误:乐观更新被正在进行的请求覆盖 预防方法:始终在 onMutate 中调用 cancelQueries:

onMutate(id) {
  cache.cancelQueries({ key: ['todos'] })
  // Then do optimistic update
}

参见:references/error-catalog.md #2

错误 #3:SSR 水合不匹配

错误:Hydration completed but contains mismatches 预防方法:为 SSR 查询设置 refetchOnMount: false

useQuery({
  key: ['todos'],
  query: fetchTodos,
  refetchOnMount: false, // Prevents SSR hydration mismatch
})

参见:references/error-catalog.md #3

错误 #4:查询键不具备响应性

错误:变量变化时查询不会重新获取数据 预防方法:使用函数创建响应式键:

// ❌ Wrong - static key
key: ['todos', id.value]

// ✅ Correct - reactive key
key: () => ['todos', id.value]

参见:references/error-catalog.md #4

错误 #5:Nuxt 模块顺序错误

错误:PiniaColada plugin not found 或 SSR 错误 预防:始终将 @pinia/nuxt 放在最前面:

export default defineNuxtConfig({
  modules: [
    '@pinia/nuxt',           // MUST be first
    '@pinia/colada-nuxt',    // Then Colada
  ],
})

参见:references/error-catalog.md #10

完整错误目录(全部 12 个错误):参见 references/error-catalog.md


使用捆绑资源

参考文档(references/)

按需加载的详细指南:

  • references/setup-guide.md - 完整的 8 步设置流程

    • 安装并配置插件
    • 创建可复用的查询组合式函数
    • 了解查询键
    • 实现变更
    • 乐观更新
    • 查询失效策略
    • 分页查询
    • SSR 和 Nuxt 集成
    • 加载时机:用户需要详细的设置说明或高级模式时
  • references/common-patterns.md - 12 种常见模式

    • 依赖查询
    • 并行查询
    • 条件查询
    • 后台同步模式
    • 悬停时预取
    • 使多个查询失效的变更
    • 无限查询
    • 乐观删除
    • 带重试逻辑的查询
    • 轮询查询
    • 查询缓存预填充
    • 手动触发查询
    • 加载时机:用户询问“如何……”或需要特定模式时
  • references/error-catalog.md - 全部 12 个已记录的错误

    • 完整的错误消息和解决方案
    • 预防策略
    • 引用官方来源
    • 预防检查清单
    • 加载时机:用户遇到错误或希望预防问题时
  • references/configuration.md - 完整的配置参考

    • 插件选项(Vue 和 Nuxt)
    • 单个查询选项
    • 变更选项
    • 查询缓存方法
    • 高级模式(环境特定配置、错误处理、开发工具)
    • TypeScript 配置
    • 性能优化
    • 加载时机:用户需要配置详情或高级设置时
  • references/migration-from-tanstack-vue-query.md - 迁移指南

    • API 差异
    • Codemod 建议
    • 破坏性变更
    • 加载时机:用户提到 TanStack Vue Query 或迁移时

常见用例

  1. 基本待办事项列表,含 CRUD - 查询 + 通过失效处理的变更(10 分钟)→ 参见 references/setup-guide.md 第 2–4 步
  2. 分页数据表 - 使用 placeholderData 的响应式键(15 分钟)→ 参见 references/setup-guide.md 第 7 步
  3. 乐观 UI 更新 - 使用 onMutate/onError 回滚的变更(20 分钟)→ 参见 references/setup-guide.md 第 5 步
  4. Nuxt SSR 应用 - 配合 refetchOnMount 配置使用自动导入(15 分钟)→ 参见 references/setup-guide.md 第 8 步
  5. 实时仪表板 - 使用 refetchInterval 进行后台轮询(10 分钟)→ 参见 references/common-patterns.md 模式 4

全部 5 个用例的完整代码示例,请参见 references/setup-guide.md 和 references/common-patterns.md。


何时加载详细参考文档

在以下情况下加载 references/setup-guide.md:

  • 用户需要完整的 8 步设置流程
  • 用户询问查询键或响应式键
  • 用户需要了解如何实现乐观更新
  • 用户询问 SSR/Nuxt 设置
  • 用户需要实现分页

在以下情况下加载 references/common-patterns.md:

  • 用户询问“如何……”并接着提出特定模式
  • 用户需要依赖查询
  • 用户询问预取
  • 用户需要无限滚动
  • 用户询问轮询或后台同步

在以下情况下加载 references/error-catalog.md:

  • 用户遇到任何错误
  • 用户询问故障排查
  • 用户希望预防已知问题
  • 用户询问“有哪些错误需要留意?”
  • 用户遇到 SSR 水合问题

在以下情况下加载 references/configuration.md:

  • 用户需要完整的配置选项
  • 用户询问插件配置
  • 用户需要 TypeScript 类型
  • 用户希望优化性能
  • 用户需要自定义插件

在以下情况下加载 references/migration-from-tanstack-vue-query.md:

  • 用户提到 TanStack Vue Query
  • 用户询问迁移
  • 用户比较 Pinia Colada 与 TanStack Query
  • 用户询问“与……有什么不同”

依赖项

必需:

可选:


官方文档


软件包版本(已于 2025-11-28 验证)

{
  "dependencies": {
    "@pinia/colada": "^0.17.9",
    "pinia": "^3.0.4",
    "vue": "^3.5.25"
  },
  "devDependencies": {
    "@pinia/colada-nuxt": "^0.17.9"
  }
}

版本说明:

  • Pinia Colada 0.17.9 是最新稳定版本(于 2025-11-21 发布)
  • 兼容 Pinia 2.2.6+ 和 3.0+
  • 需要 Vue 3.5.17+ 以获得最佳响应性
  • Nuxt 模块版本与核心软件包一致

生产环境示例

此技能基于多个 Vue 3 和 Nuxt 应用中的生产环境实践:

  • 节省 Token:相比手动配置 TanStack Query,约节省 65%
  • 避免的错误:上文记录了 12 个常见问题
  • 构建时间:基础配置少于 2 分钟
  • 验证结果:✅ SSR 正常运行,✅ TypeScript 类型正确,✅ Nuxt 中自动导入正常

完整配置检查清单

使用此清单验证你的配置:

  • 已安装 @pinia/colada 和 pinia(Nuxt 项目则安装 @pinia/colada-nuxt)
  • 已在 createPinia() 之后注册 PiniaColada 插件(Vue),或已将其添加到 modules(Nuxt)
  • 已使用 useQuery 创建至少一个查询
  • 已使用 useMutation 创建至少一个变更
  • 已在变更的 onSettled 钩子中使用 invalidateQueries
  • 查询键是数组(或返回数组的函数)
  • 所有查询变量都包含在查询键中
  • 查询/变更函数中抛出了错误(而不是返回错误)
  • 初始加载状态使用 isPending
  • 已为所有数据结构定义 TypeScript 类型
  • 已在插件级别配置 staleTime 和 gcTime(可选)
  • 开发环境运行时没有错误
  • 使用 Nuxt 时 SSR 正常运行(检查 hydration)

有疑问?遇到问题? 请查看:官方文档 | references/setup-guide.md(8 步流程)| references/error-catalog.md(全部 12 个错误)| references/migration-from-tanstack-vue-query.md(迁移)| GitHub


此技能提供可直接用于生产环境的 Pinia Colada 配置,且不会出现配置错误。所有 12 个常见问题均有记录并已预防。

评论

支持 Markdown