pinia-storelisted
Install: claude install-skill YuDefine/nuxt-supabase-starter
<!-- 🔒 LOCKED — managed by clade · auto-generated by sync-to-agents; edit source in .claude/ then re-run sync -->
# Pinia Store 架構規範
## 目錄結構
```
app/stores/
├── userPreferences.ts # 使用者偏好設定
├── auth.ts # 認證狀態
└── ui.ts # UI 全域狀態
```
## Store 模板
使用 Composition API 語法:
```typescript
import { defineStore } from 'pinia'
export const useMyStore = defineStore('my-store', () => {
const items = ref<Item[]>([])
const isLoading = ref(false)
const error = ref<Error | null>(null)
const itemCount = computed(() => items.value.length)
async function loadItems() {
isLoading.value = true
error.value = null
try {
const data = await $fetch('/api/v1/items')
items.value = data
} catch (e) {
error.value = e as Error
} finally {
isLoading.value = false
}
}
return {
items: readonly(items),
isLoading: readonly(isLoading),
error: readonly(error),
itemCount,
loadItems,
}
})
```
## 命名規範
- Store 函式:`use<Name>Store`
- Store ID:`kebab-case`
```typescript
// ✅
export const useUserPreferencesStore = defineStore('user-preferences', ...)
// ❌
export const userPreferencesStore = defineStore('preferences', ...)
```
## 使用方式
```vue
<script setup lang="ts">
const store = useMyStore()
// 解構保持響應性
const { items, isLoading } = storeToRefs(store)
const { loadItems } = store
</script>
```
## 重要原則
- 使用 `readonly()` 保護回傳的狀態,通過 action 修改
- 避免在 Store 中使用 `useState`,使用 `ref` 替代
- 錯誤處理:tr