核心修練
CoreState

狀態管理

在 SSR 框架中,狀態管理比純 SPA 複雜。Nuxt 提供了 useState 組合式函數,解決了伺服器端與客戶端狀態同步的難題。

為什麼需要 useState?

你可能會問:「為什麼不能直接用 Vue 的 ref?」
答案在於 **SSR (伺服器端渲染)** 的運作機制。

使用 ref 的風險

如果在 setup() 外部定義全域 ref, 這個變數會在 Node.js 伺服器記憶體中被所有使用者的請求共享

// 危險!所有使用者會看到同一個 counter
const globalCounter = ref(0)

useState 的保護

useState 會在伺服器端為每個請求建立獨立的狀態實例, 並自動將資料序列化 (Serialize) 傳送到客戶端,完成水合 (Hydration)。

// 安全。每個請求都有獨立的 counter
const counter = useState('count', () => 0)

實驗室:Local vs Shared State

試著操作下方的按鈕。你會發現 ref (Local) 只會影響單一元件, 而 useState (Shared) 則會同步更新所有使用該 Key 的元件。

Component A
Local State (ref)Isolated
0
Shared State (useState)
0
Component B
Local State (ref)Isolated
0
Shared State (useState)
0
Auto-synced

基本用法

useState 接受兩個參數:一個唯一的 key (字串) 和一個初始化函數。

app.vue
<script setup>
// 'counter' 是全域唯一的 key
const count = useState('counter', () => 0)

const increment = () => {
  count.value++
}
</script>

<template>
  <button @click='increment'>
    Count: {{ count }}
  </button>
</template>

參數說明

  • 1
    Key (String)

    用於識別狀態的唯一鍵值。如果在不同元件使用相同的 key,它們會共享同一個狀態。

  • 2
    Init (Function)

    初始化函數。只會在狀態尚未存在時執行一次。

自動 Key 生成

如果你在元件的 script setup 頂層使用,Nuxt 可以自動為你生成 key,但在 Composables 中建議手動指定。


跨元件共享

結合 ComposablesuseState,我們可以建立輕量級的全域狀態管理系統。

1. 定義 Composable

app/composables/useColor.ts
// app/composables/useColor.ts
export const useColor = () => {
  return useState('color', () => 'pink')
}

2. 在任何元件中使用

ComponentA.vue
<script setup>
const color = useColor() // 'pink'
</script>
ComponentB.vue
<script setup>
const color = useColor()
// 修改會同步到 ComponentA
color.value = 'blue' 
</script>

進階:Pinia

雖然 useState 足夠應付簡單場景,但當應用程式變得複雜時, 官方推薦使用 Pinia

  • DevTools 支援 (時光旅行除錯)
  • 熱模組替換 (HMR)
  • 更完整的 TypeScript 型別推斷