Vue狀態管理庫Pinia詳解

威哥爱编程發表於2024-08-23

Pinia 是 Vue 的狀態管理庫,它提供了一種更簡單、更不規範的 API 來管理應用的狀態。Pinia 的設計哲學是簡單性和易用性,它避免了 Vuex 中的許多複雜概念,如 mutations 和模組的巢狀結構,提供了一種更現代、更符合 Vue 3 Composition API 風格的狀態管理方式。

先來瞅一眼 Pinia 的核心元件主要包括以下幾個方面:

  1. Store:Pinia 中的 Store 是一個儲存狀態和業務邏輯的實體,它不與元件樹繫結,可以在整個應用中訪問。Store 包含三個核心概念:state(狀態)、getters(獲取器)、actions(動作)。這些概念類似於元件中的 data、computed 和 methods。

  2. defineStore() :這是定義 Store 的函式,需要傳入一個獨一無二的名字作為 ID,用於連線 Store 和 devtools。Store 可以透過 Setup 函式或 Option 物件來定義。

  3. reactive:雖然 Pinia 本身不要求使用 Composition API,但它與 Vue 的 reactive 系統緊密整合,允許開發者以宣告式的方式管理狀態。

  4. Devtools 支援:Pinia 支援 Vue Devtools,提供了追蹤 actions 和 mutations 的時間線、時間旅行和熱更新等功能,方便開發者除錯。

  5. 外掛系統:Pinia 允許透過外掛來擴充套件其功能,例如支援伺服器端渲染或新增額外的中介軟體。

  6. TypeScript 支援:Pinia 提供了對 TypeScript 的良好支援,包括型別推斷和自動補全功能,使得在 TypeScript 專案中使用 Pinia 更加方便 。

  7. SSR 支援:Pinia 支援服務端渲染,這對於構建需要 SSR 的應用是一個重要的特性。

  8. 對映輔助函式:Pinia 提供瞭如 mapStores、mapState 和 mapActions 等輔助函式,使得在元件中使用 Store 更加方便。

下面是每個部分的詳細介紹。

1. Store

在 Pinia 中,Store 是用來封裝應用的狀態和邏輯的核心概念。它允許你將狀態和行為集中管理,而不是分散在各個元件中。Store 可以包含以下幾部分:

  • state:狀態資料,通常是響應式的,可以在元件中被讀取和修改。
  • getters:計算屬性,用於派生狀態,它們是響應式的,並且可以被快取。
  • actions:可以包含任意的非同步操作或同步操作,用於修改狀態或執行復雜的業務邏輯。

案例實現

下面是一個建立 Store 的步驟解析,包括程式碼示例:

步驟 1: 定義 Store

首先,你需要從 Pinia 匯入 defineStore 函式,並使用它來定義一個新的 Store

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    users: [] // 初始狀態是一個空陣列
  }),
  getters: {
    // 一個 getter 函式,返回陣列中的使用者數量
    count: (state) => state.users.length
  },
  actions: {
    // 一個 action 函式,用於新增使用者
    addUser(user) {
      this.users.push(user)
    }
  }
})

步驟 2: 在元件中使用 Store

在 Vue 元件中,你可以透過呼叫你定義的 useUserStore 函式來使用這個 Store

<template>
  <div>
    <button @click="addNewUser">新增使用者</button>
    <p>使用者總數: {{ userCount }}</p>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import useUserStore from '@/stores/user'

const store = useUserStore()
const users = computed(() => store.users)
const userCount = computed(() => store.count)

function addNewUser() {
  store.addUser({ id: Date.now(), name: '新使用者' })
}
</script>

程式碼解析

  • 匯入 defineStore:從 Pinia 匯入 defineStore 函式來定義新的 Store
  • 定義 useUserStore:建立一個名為 useUserStore 的函式,它返回一個 Store 物件。
  • state:在 Store 中定義了一個狀態 users,初始為空陣列。
  • getters:定義了一個 count getter,它返回 users 陣列的長度。
  • actions:定義了一個 addUser action,它接受一個使用者物件並將其新增到 users 陣列中。
  • 在元件中使用:在元件的 <script setup> 塊中,透過呼叫 useUserStore 來獲取 Store 例項,並使用 computed 來建立響應式的 usersuserCount
  • 新增使用者:定義了一個 addNewUser 函式,當按鈕被點選時,呼叫 store.addUser 來新增新使用者。

以上案例展示瞭如何在 Pinia 中建立和管理狀態,以及如何在 Vue 元件中使用 Store。透過這種方式,你可以集中管理狀態,使得狀態邏輯更加清晰和可維護。

2. defineStore()

defineStore() 是 Pinia 中用於定義 Store 的函式。它允許你以宣告式的方式建立一個狀態管理單元,這個單元可以包含狀態(state)、獲取器(getters)、動作(actions)等。defineStore() 函式接受一個唯一的 ID 和一個配置物件,配置物件中可以定義 state、getters、actions 等屬性。

案例實現

下面是一個使用 defineStore() 建立 Store 的步驟解析,包括程式碼示例:

步驟 1: 匯入 defineStore

首先,需要從 Pinia 匯入 defineStore 函式。

import { defineStore } from 'pinia'

步驟 2: 定義 Store

使用 defineStore() 定義一個新的 Store,傳入一個唯一的 ID 和一個配置物件。

export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] // 購物車初始狀態為空陣列
  }),
  getters: {
    // 計算屬性,返回購物車中商品的總數量
    itemCount(state) {
      return state.items.reduce((total, item) => total + item.quantity, 0)
    }
  },
  actions: {
    // 新增商品到購物車的動作
    addItem(item) {
      const index = this.items.findIndex(i => i.id === item.id)
      if (index > -1) {
        // 如果商品已存在,則增加數量
        this.items[index].quantity += item.quantity
      } else {
        // 否則,新增新商品
        this.items.push(item)
      }
    },
    // 清空購物車的動作
    clearCart() {
      this.items = []
    }
  }
})

步驟 3: 在元件中使用 Store

在 Vue 元件中,透過呼叫 useCartStore 來使用這個 Store。

<template>
  <div>
    <button @click="addItem">新增商品</button>
    <button @click="clearCart">清空購物車</button>
    <p>商品總數: {{ itemCount }}</p>
    <ul>
      <li v-for="item in cartItems" :key="item.id">
        {{ item.name }} - 數量: {{ item.quantity }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import useCartStore from '@/stores/cart'

const store = useCartStore()
const cartItems = computed(() => store.items)
const itemCount = computed(() => store.itemCount)

function addItem() {
  store.addItem({ id: 1, name: '商品A', quantity: 1 })
}

function clearCart() {
  store.clearCart()
}
</script>

程式碼解析

  • 匯入 defineStore:從 Pinia 匯入 defineStore 函式。
  • 定義 useCartStore:建立一個名為 useCartStore 的函式,它返回一個配置好的 Store 物件。
  • state:在 Store 中定義了一個狀態 items,初始為空陣列,用於儲存購物車中的商品。
  • getters:定義了一個 itemCount getter,它透過遍歷 items 陣列並累加每個商品的 quantity 來計算總數量。
  • actions:定義了 addItemclearCart 兩個 actions。addItem 用於向購物車新增商品,如果商品已存在則增加其數量;clearCart 用於清空購物車。
  • 在元件中使用:在元件的 <script setup> 塊中,透過呼叫 useCartStore 來獲取 Store 例項,並使用 computed 來建立響應式的 cartItemsitemCount
  • 新增和清空商品:定義了 addItemclearCart 函式,分別用於新增商品和清空購物車。

使用 defineStore() 建立一個包含狀態、獲取器和動作的 Store,並在 Vue 元件中使用這個 Store 來管理購物車的狀態。透過這種方式,你可以將狀態邏輯封裝在 Store 中,使得元件更加簡潔和易於管理。

3. reactive

reactive() 是 Vue 3 的 Composition API 中的一個函式,它用於建立響應式的狀態物件。當使用 reactive() 建立一個物件後,Vue 會追蹤這個物件中屬性的讀取和修改,並且在資料變化時通知依賴於這些資料的元件重新渲染。

Pinia 與 Vue 的響應式系統緊密整合,reactive() 通常在定義 Store 的狀態時使用。在 Pinia 中,狀態(state)是一個透過 reactive() 建立的響應式物件,因此任何對狀態的修改都會自動觸發與該狀態相關的元件更新。

案例實現

下面是一個使用 reactive() 來建立響應式狀態的步驟解析:

步驟 1: 匯入 reactive

首先,需要從 Vue 匯入 reactive 函式。

import { reactive } from 'vue'

步驟 2: 使用 reactive 建立狀態

使用 reactive() 函式來建立一個響應式的狀態物件。

const state = reactive({
  count: 0, // 初始狀態
  message: 'Hello, Pinia!' // 初始訊息
})

步驟 3: 在 Pinia Store 中使用 reactive 狀態

在 Pinia 的 defineStore() 中,可以直接使用 reactive() 來定義狀態。

import { defineStore } from 'pinia'
import { reactive } from 'vue'

export const useMyStore = defineStore('myStore', {
  state: () => reactive({
    count: 0,
    message: 'Hello, Pinia!'
  }),
  // 其他 getters 和 actions 可以在這裡定義
})

步驟 4: 在元件中使用 Store

在 Vue 元件中,透過呼叫 useMyStore 來使用這個 Store,並訪問響應式狀態。

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Message: {{ message }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import useMyStore from '@/stores/myStore'

const store = useMyStore()
const count = computed(() => store.state.count)
const message = computed(() => store.state.message)

function increment() {
  store.state.count++
}
</script>

程式碼解析

  • 匯入 reactive:從 Vue 匯入 reactive 函式。
  • 建立響應式狀態:使用 reactive() 建立一個包含 countmessage 的響應式狀態物件。
  • 在 Pinia Store 中使用 reactive:在 defineStore()state 函式中返回一個 reactive() 物件,這樣 Pinia 就可以管理這個狀態的響應性。
  • 在元件中使用:在元件的 <script setup> 塊中,透過呼叫 useMyStore 來獲取 Store 例項。使用 computed 來確保訪問狀態時保持響應性。
  • 修改狀態:定義了一個 increment 函式,當按鈕被點選時,直接修改 store.state.count,這會觸發元件的更新。

透過這種方式,你可以確保狀態的任何變化都會自動傳播到使用這些狀態的元件中,實現響應式的資料流,你get到了嗎。

4. Devtools 支援

Vue Devtools 是一個瀏覽器擴充套件,它為開發 Vue 應用提供了強大的除錯支援。對於 Pinia 來說,Devtools 支援意味著你可以在開發過程中更直觀地檢視和操作應用的狀態。

Pinia 與 Vue Devtools 整合,提供了以下功能:

  • 狀態檢視:可以在 Devtools 中檢視所有 Pinia Store 的狀態。
  • 時間旅行:回溯狀態的歷史,檢視狀態的變化過程。
  • 動作追蹤:記錄和展示 Store 中 actions 的呼叫歷史,包括引數和執行時間。
  • 狀態修改:允許你在 Devtools 中直接修改狀態,這些修改會實時反映到應用中。
  • 持久化狀態:在開發過程中保持狀態不變,即使頁面重新整理或元件重新渲染。

案例實現

要充分利用 Pinia 的 Devtools 支援,你需要確保正確安裝和配置了 Vue Devtools,並且正確地在你的 Pinia Store 中編寫程式碼。來吧,一步一步跟著做就行:

步驟 1: 安裝 Vue Devtools

首先,確保你已經安裝了 Vue Devtools 瀏覽器擴充套件。你可以從 Chrome Web Store 或 Firefox Add-ons 等地方安裝。

步驟 2: 建立 Pinia Store

建立一個 Pinia Store,並定義 state、getters 和 actions。

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

步驟 3: 在 Vue 應用中使用 Pinia

在你的 Vue 應用中建立 Pinia 例項,並在應用啟動時使用它。

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

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

app.use(pinia)
app.mount('#app')

步驟 4: 使用 Store

在元件中使用你的 Store,並執行一些狀態更改的動作。

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import useCounterStore from '@/stores/counter'

const store = useCounterStore()
const count = computed(() => store.count)

function increment() {
  store.increment()
}
</script>

步驟 5: 使用 Vue Devtools 除錯

  • 開啟瀏覽器的開發者工具。
  • 切換到 Vue Devtools 皮膚。
  • 在“Components”或“Store”標籤頁中,你應該能看到你的 Pinia Store。
  • 展開 Store,檢視 state、getters 和 actions。
  • 點選 actions,你可以看到它們的呼叫歷史和引數。
  • 直接在 Devtools 中修改 state 的值,看應用如何響應這些變化。

程式碼過程步驟解析

  • 安裝 Devtools:確保瀏覽器擴充套件已安裝。
  • 建立 Store:使用 defineStore 建立一個包含 state、getters 和 actions 的 Pinia Store。
  • 應用配置:在應用啟動時建立 Pinia 例項並使用它。
  • 元件使用:在元件中透過呼叫 Store 函式來獲取 Store 例項,並使用 computed 屬性來保持響應性。
  • 除錯:使用 Vue Devtools 檢視和修改狀態,追蹤 actions。

利用 Vue Devtools 提供的功能來除錯使用 Pinia 管理狀態的 Vue 應用,感覺是不是挺爽。

5. 外掛系統

Pinia 的外掛系統允許開發者擴充套件 Pinia 的功能。外掛可以訪問 Pinia 的 Store 建立過程,可以執行以下操作:

  • 在 Store 建立之前或之後執行自定義邏輯。
  • 攔截 Store 的 stategettersactions 等屬性。
  • 向 Store 新增自定義屬性或方法。
  • 處理 Store 的銷燬邏輯。

Pinia 外掛通常在建立 Pinia 例項時註冊,然後 Pinia 會將外掛應用到每個建立的 Store 上。

案例實現

下面是一個建立和使用 Pinia 外掛的步驟解析,包括程式碼示例:

步驟 1: 定義外掛

首先,定義一個外掛函式,該函式接收 Pinia 的例項作為引數。

function myPiniaPlugin(pinia) {
  // 外掛邏輯
}

步驟 2: 外掛邏輯

在外掛函式內部,可以訪問 Pinia 的 store 物件,並對其進行操作。

function myPiniaPlugin(pinia) {
  pinia.use((store) => {
    // 可以在此處訪問 store.state, store.getters, store.actions 等
    // 例如,向 store 新增一個新屬性
    store.myCustomProperty = 'Hello from plugin!'
  })
}

步驟 3: 建立 Pinia 例項並使用外掛

建立 Pinia 例項時,使用 use 方法註冊外掛。

import { createPinia } from 'pinia'

const pinia = createPinia().use(myPiniaPlugin)

步驟 4: 建立 Store

定義一個 Store,使用 defineStore 函式。

import { defineStore } from 'pinia'

export const useMyStore = defineStore('myStore', {
  // state, getters, actions 定義
  state: () => ({
    value: 0
  }),
  // 其他選項...
})

步驟 5: 在元件中使用 Store

在元件中使用 Store,並訪問外掛新增的屬性。

<template>
  <div>
    <p>Value: {{ value }}</p>
    <p>Plugin Property: {{ store.myCustomProperty }}</p>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import useMyStore from '@/stores/myStore'

const store = useMyStore()
const value = computed(() => store.value)
</script>

步驟 6: 元件中使用外掛屬性

在元件的模板或指令碼中,使用外掛新增到 Store 的自定義屬性。

// 在模板中
<p>Plugin Property: {{ store.myCustomProperty }}</p>

// 在指令碼中
console.log(store.myCustomProperty) // 輸出: Hello from plugin!

程式碼過程步驟解析

  • 定義外掛:建立一個函式,該函式接收 Pinia 例項並定義外掛邏輯。
  • 外掛邏輯:在外掛函式內部,使用 pinia.use 方法註冊一個回撥,該回撥接收每個 Store 並可以對其進行操作。
  • 註冊外掛:在建立 Pinia 例項時,透過 .use() 方法註冊外掛。
  • 建立 Store:使用 defineStore 定義 Store,包括 state、getters、actions。
  • 使用 Store:在元件中使用 Store,並利用 computed 屬性保持響應性。
  • 訪問外掛屬性:在元件的模板或指令碼中,訪問外掛新增到 Store 的自定義屬性。

記住這一點,開發者需要新增自定義邏輯和屬性,透過Pinia 外掛系統就 OK。

6. TypeScript 支援

Pinia 為 TypeScript 使用者提供了一流的支援,確保型別安全和開發體驗。Pinia 的 TypeScript 支援主要體現在以下幾個方面:

  1. 型別推斷:Pinia 利用 TypeScript 的高階型別系統來推斷 Store 中的狀態、getters 和 actions 的型別。
  2. 型別宣告:Pinia 提供了型別宣告檔案(.d.ts),確保 Pinia API 在 TypeScript 專案中的型別正確性。
  3. 自動補全:在 TypeScript 環境中,編輯器可以提供自動補全功能,幫助開發者快速編寫程式碼。
  4. 型別守衛:Pinia 與 TypeScript 配合使用時,可以利用型別守衛來確保對 Store 屬性的訪問是安全的。

案例實現

下面是一個使用 TypeScript 與 Pinia 結合使用的步驟解析,包括程式碼示例:

步驟 1: 設定 TypeScript 環境

確保你的專案已經配置了 TypeScript,並且安裝了必要的型別宣告檔案。

npm install typescript @vue/compiler-sfc

步驟 2: 定義 Store 使用 TypeScript

使用 TypeScript 的型別定義來建立 Pinia Store。

import { defineStore } from 'pinia'

interface State {
  count: number
  message: string
}

export const useMyStore = defineStore('myStore', {
  state: (): State => ({
    count: 0,
    message: 'Hello, Pinia with TypeScript!'
  }),
  getters: {
    // 使用 TypeScript 來宣告 getter 的返回型別
    doubleCount: (state): number => state.count * 2
  },
  actions: {
    increment(): void {
      this.count++
    }
  }
})

步驟 3: 在元件中使用 Store

在 Vue 元件中使用 Store,並利用 TypeScript 提供型別安全。

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Message: {{ message }}</p>
    <p>Double Count: {{ doubleCount }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import useMyStore from '@/stores/myStore'

const store = useMyStore()
const count = computed(() => store.count)
const message = computed(() => store.message)
const doubleCount = computed(() => store.doubleCount)

function increment() {
  store.increment()
}
</script>

步驟 4: 利用型別守衛

使用型別守衛來確保對 Store 屬性的訪問是安全的。

if (store.hasOwnProperty('count')) {
  // TypeScript 知道 'count' 存在且為 number 型別
  console.log(store.count)
}

程式碼過程步驟解析

  • 配置 TypeScript:確保專案中安裝了 TypeScript 及其型別宣告檔案。
  • 定義 Store 型別:使用 TypeScript 的介面(interface)來定義 Store 的狀態型別。
  • 建立 Store:使用 defineStore 並傳入型別化的 state 函式,以及宣告瞭返回型別的 getters 和 actions。
  • 元件中使用 Store:在元件中使用 TypeScript 來確保訪問 Store 屬性的型別安全。
  • 型別守衛:使用 TypeScript 的 hasOwnProperty 方法和型別守衛來安全地訪問 Store 的屬性。

小結一下,Pinia 與 TypeScript 結合使用可以提供型別安全的狀態管理,同時編輯器的自動補全和型別檢查功能可以提高開發效率和減少錯誤。

7. SSR 支援

伺服器端渲染(SSR)是一種將網站頁面在伺服器上生成併傳送給客戶端的技術。對於狀態管理庫來說,SSR 支援意味著可以在伺服器上初始化和操作狀態,然後將狀態序列化後傳送到客戶端,客戶端再將這些狀態恢復以保持與伺服器端相同的狀態。

Pinia 對 SSR 的支援主要體現在以下幾個方面:

  1. 狀態序列化:Pinia 允許將狀態(state)序列化成 JSON 字串,以便在伺服器和客戶端之間傳輸。
  2. 狀態恢復:客戶端可以接收伺服器端的狀態,並將其恢復到對應的 Store 中。
  3. 無狀態的 Store 定義:Pinia 的 Store 定義是無狀態的,這意味著在伺服器端和客戶端端都可以重新建立 Store。
  4. 與 Vue SSR 的整合:Pinia 可以與 Vue 的 SSR 系統整合,確保在伺服器端預渲染元件時使用正確的狀態。

案例實現

下面是一個使用 Pinia 進行 SSR 的步驟解析,包括程式碼示例:

步驟 1: 定義 Store

首先,定義一個 Pinia Store。

import { defineStore } from 'pinia'

export const useMyStore = defineStore('myStore', {
  state: () => ({
    count: 0
  }),
  // 其他選項...
})

步驟 2: 在伺服器端建立和序列化狀態

在伺服器端,建立 Store 例項並初始化狀態,然後將狀態序列化。

// server.js
import { createPinia } from 'pinia'
import useMyStore from '@/stores/myStore'

const pinia = createPinia()

// 模擬從資料庫獲取初始狀態
const initialState = { count: 10 }

// 建立 Store 例項並設定初始狀態
const store = useMyStore(pinia)
store.$state.count = initialState.count

// 序列化狀態
const stateToTransfer = JSON.stringify(store.$state)

步驟 3: 在客戶端恢復狀態

在客戶端,接收伺服器端傳送的狀態,然後恢復到對應的 Store 中。

// client.js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue' // Vue 應用的根元件
import useMyStore from '@/stores/myStore'

const pinia = createPinia()

// 假設從伺服器接收的狀態如下
const stateFromServer = JSON.parse(/* state serialized from server */)

// 建立 Store 例項並恢復狀態
const store = useMyStore(pinia)
store.$state.count = stateFromServer.count

const app = createApp(App)
app.use(pinia)
app.mount('#app')

步驟 4: 在 Vue 元件中使用 Store

在 Vue 元件中,像平常一樣使用 Store。

<template>
  <div>{{ count }}</div>
</template>

<script setup>
import { computed } from 'vue'
import useMyStore from '@/stores/myStore'

const store = useMyStore()
const count = computed(() => store.count)
</script>

程式碼過程步驟解析

  • 定義 Store:使用 defineStore 定義一個 Pinia Store。
  • 伺服器端建立和序列化:在伺服器端,建立 Store 例項,設定初始狀態,並使用 JSON.stringify 序列化狀態。
  • 客戶端恢復狀態:在客戶端,解析伺服器端傳送的狀態字串,並恢復到 Store 的 $state 中。
  • 元件中使用 Store:在 Vue 元件中,透過呼叫 Store 函式獲取 Store 例項,並使用 computed 屬性來訪問狀態。

一句話,Pinia支援SSR有助於提高應用的初始載入效能和SEO最佳化。

8. 對映輔助函式

在 Pinia 中,對映輔助函式用於將 Store 中的狀態(state)、獲取器(getters)、動作(actions)對映到元件的計算屬性(computed properties)、方法(methods)或響應式屬性上。這些輔助函式提供了一種便捷的方式來使用 Store,而無需在每個元件中重複編寫相同的程式碼。

Pinia 的對映輔助函式主要包括:

  • mapState:將 Store 中的狀態對映為元件的計算屬性。
  • mapGetters:將 Store 中的獲取器對映為元件的計算屬性。
  • mapActions:將 Store 中的動作對映為元件的方法。

案例實現

下面是一個使用 Pinia 對映輔助函式的步驟解析,包括程式碼示例:

步驟 1: 定義 Store

首先,定義一個 Pinia Store。

import { defineStore } from 'pinia'

export const useCartStore = defineStore('cart', {
  state: () => ({
    items: []
  }),
  getters: {
    itemCount: (state) => state.items.length
  },
  actions: {
    addItem(item) {
      this.items.push(item)
    }
  }
})

步驟 2: 使用對映輔助函式

在元件中,使用 mapStatemapGettersmapActions 將 Store 的屬性對映到元件上。

<template>
  <div>
    <p>Item Count: {{ itemCount }}</p>
    <button @click="addItem({ id: 1, name: 'Apple' })">Add Apple</button>
  </div>
</template>

<script setup>
import { mapState, mapGetters, mapActions } from 'pinia'
import useCartStore from '@/stores/cart'

const store = useCartStore()

// 使用 mapState 對映狀態
const items = mapState(store, 'items')

// 使用 mapGetters 對映獲取器
const itemCount = mapGetters(store, 'itemCount')

// 使用 mapActions 對映動作
const { addItem } = mapActions(store, ['addItem'])
</script>

步驟 3: 在模板中使用對映的屬性

在元件的模板中,直接使用對映的計算屬性和方法。

<p>Item Count: {{ itemCount }}</p>
<button @click="addItem({ id: 1, name: 'Apple' })">Add Apple</button>

程式碼過程步驟解析

  • 定義 Store:使用 defineStore 定義一個包含狀態、獲取器和動作的 Pinia Store。
  • 使用對映輔助函式
    • mapState:將 items 狀態對映為元件的計算屬性。
    • mapGetters:將 itemCount 獲取器對映為元件的計算屬性。
    • mapActions:將 addItem 動作對映為元件的方法。
  • 模板中使用:在模板中,使用對映的計算屬性 itemCount 來顯示專案數量,使用對映的方法 addItem 來新增新專案。

使用對映輔助函式,Pinia 可以讓開發者以宣告式的方式在元件中使用 Store 的狀態和行為,從而減少樣板程式碼並提高元件的可讀性和可維護性。此外,這些輔助函式還有助於保持響應性,確保當 Store 中的狀態變化時,元件能夠自動更新。

最後

不得不說,Pinia 提供了一種靈活且高效的方式來管理 Vue 應用的狀態,無論是在單頁應用還是伺服器端渲染的場景下,都有出色的表現,寫完收工,歡迎關注威哥愛程式設計,一起走全棧之路。

相關文章