19
Re:Nuxt 100 天練習曲
Day 19

專業的狀態管理大師 (Pinia)

Day 19·Pinia·Store

1. 為什麼需要 Pinia?

useState 很好用,但當您的應用程式變大,狀態邏輯越來越複雜時,您可能會遇到一些挑戰:

邏輯分散

修改狀態的程式碼可能散落在各個元件中,難以追蹤。

缺乏結構

沒有統一的地方來定義「可以對這個狀態做哪些操作」。

難以除錯

當狀態出錯時,很難知道是哪個元件把它改壞的。

Pinia 就是為了解決這些問題而生的。您可以把它想像成是為您的共享狀態,建立一個專門的管理部門

2. Pinia 的核心概念:Store

在 Pinia 中,每一個「共享狀態」都會被定義在一個稱為 Store 的檔案裡。這個 Store 就像一個部門,它清楚地劃分了三種職責:

state:部門的資料庫

這是一個函式,用來存放這個部門最核心的資料。就像 useState 的初始值。

actions:部門的行動方案

這是一個物件,用來定義「可以對資料做哪些事」。所有修改 state非同步複雜同步邏輯都應該寫在這裡。例如,從 API 獲取使用者資料並更新 state

getters:部門的報告產生器

這是一個物件,用來定義如何從 state 中衍生出新的資料,就像 Vue 的 computed。例如,從購物車的商品清單中,計算出總金額。

3. 在 Nuxt 中使用 Pinia

得益於 Nuxt 強大的模組生態系,整合 Pinia 變得輕而易舉。

1

第一步:安裝模組

打開終端機,執行 Nuxt 提供的指令:

Terminal
npx nuxt module add pinia

這個指令會幫您安裝好所有需要的套件,並在 nuxt.config.ts 中自動設定好模組。

2

第二步:建立您的第一個 Store

在 stores/ 資料夾中建立一個檔案,例如 user.ts。

stores/user.ts
// stores/user.ts
import { defineStore } from 'pinia';

// defineStore('唯一的 Store ID', { ...設定 })
export const useUserStore = defineStore('user', {
  // 1. 資料庫 (State)
  state: () => ({
    isLoggedIn: false,
    name: '訪客'
  }),

  // 2. 報告產生器 (Getters)
  getters: {
    welcomeMessage: (state) => `你好,${state.name}`
  },

  // 3. 行動方案 (Actions)
  actions: {
    login(username) {
      this.isLoggedIn = true;
      this.name = username;
    },
    logout() {
      this.isLoggedIn = false;
      this.name = '訪客';
    }
  }
})
3

第三步:在元件中使用 Store

現在,在任何元件中,您都可以像呼叫 composable 一樣,來取得並操作這個 Store。

在元件中使用 Store
<script setup>
import { useUserStore } from '~/stores/user';

// 取得 user Store 的實體
const userStore = useUserStore();
</script>

<template>
  <div>
    <p>{{ userStore.welcomeMessage }}</p>

    <div v-if="userStore.isLoggedIn">
      <button @click="userStore.logout()">登出</button>
    </div>
    <div v-else>
      <button @click="userStore.login('Re:Human')">登入</button>
    </div>
  </div>
</template>

今日總結

今天我們學會了使用 Pinia 來建立一個結構清晰、權責分明的狀態管理系統。

Store 是 Pinia 的核心,它將 state、getters 和 actions 整合在一起。

State

存放資料。

Getters

衍生資料。

Actions

修改資料。

當您的應用程式規模擴大時,Pinia 將是您管理複雜狀態時最得力的助手!