Pinia詳解:Vue狀態(tài)管理庫的簡單易用性

2024-12-18 11:12 更新

大家好,我是 V 哥。Pinia 是 Vue 的狀態(tài)管理庫,它提供了一種更簡單、更不規(guī)范的 API 來管理應(yīng)用的狀態(tài)。Pinia 的設(shè)計哲學(xué)是簡單性和易用性,它避免了 Vuex 中的許多復(fù)雜概念,如 mutations 和模塊的嵌套結(jié)構(gòu),提供了一種更現(xiàn)代、更符合 Vue 3 Composition API 風(fēng)格的狀態(tài)管理方式。

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

  1. Store:Pinia 中的 Store 是一個保存狀態(tài)和業(yè)務(wù)邏輯的實體,它不與組件樹綁定,可以在整個應(yīng)用中訪問。Store 包含三個核心概念:state(狀態(tài))、getters(獲取器)、actions(動作)。這些概念類似于組件中的 data、computed 和 methods。

  1. defineStore() :這是定義 Store 的函數(shù),需要傳入一個獨一無二的名字作為 ID,用于連接 Store 和 devtools。Store 可以通過 Setup 函數(shù)或 Option 對象來定義。

  1. reactive:雖然 Pinia 本身不要求使用 Composition API,但它與 Vue 的 reactive 系統(tǒng)緊密集成,允許開發(fā)者以聲明式的方式管理狀態(tài)。

  1. Devtools 支持:Pinia 支持 Vue Devtools,提供了追蹤 actions 和 mutations 的時間線、時間旅行和熱更新等功能,方便開發(fā)者調(diào)試。

  1. 插件系統(tǒng):Pinia 允許通過插件來擴展其功能,例如支持服務(wù)器端渲染或添加額外的中間件。

  1. TypeScript 支持:Pinia 提供了對 TypeScript 的良好支持,包括類型推斷和自動補全功能,使得在 TypeScript 項目中使用 Pinia 更加方便 。

  1. SSR 支持:Pinia 支持服務(wù)端渲染,這對于構(gòu)建需要 SSR 的應(yīng)用是一個重要的特性。

  1. 映射輔助函數(shù):Pinia 提供了如 mapStores、mapState 和 mapActions 等輔助函數(shù),使得在組件中使用 Store 更加方便。

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

1. Store

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

  • state:狀態(tài)數(shù)據(jù),通常是響應(yīng)式的,可以在組件中被讀取和修改。
  • getters:計算屬性,用于派生狀態(tài),它們是響應(yīng)式的,并且可以被緩存。
  • actions:可以包含任意的異步操作或同步操作,用于修改狀態(tài)或執(zhí)行復(fù)雜的業(yè)務(wù)邏輯。

案例實現(xiàn)

下面是一個創(chuàng)建 Store 的步驟解析,包括代碼示例:

步驟 1: 定義 Store

首先,你需要從 Pinia 導(dǎo)入 defineStore 函數(shù),并使用它來定義一個新的 Store。

import { defineStore } from 'pinia'


export const useUserStore = defineStore('user', {
  state: () => ({
    users: [] // 初始狀態(tài)是一個空數(shù)組
  }),
  getters: {
    // 一個 getter 函數(shù),返回數(shù)組中的用戶數(shù)量
    count: (state) => state.users.length
  },
  actions: {
    // 一個 action 函數(shù),用于添加用戶
    addUser(user) {
      this.users.push(user)
    }
  }
})

步驟 2: 在組件中使用 Store

在 Vue 組件中,你可以通過調(diào)用你定義的 useUserStore 函數(shù)來使用這個 Store

<template>
  <div>
    <button @click="addNewUser">添加用戶</button>
    <p>用戶總數(shù): {{ 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>

代碼解析

  • 導(dǎo)入 defineStore:從 Pinia 導(dǎo)入 defineStore 函數(shù)來定義新的 Store。
  • 定義 useUserStore:創(chuàng)建一個名為 useUserStore 的函數(shù),它返回一個 Store 對象。
  • state:在 Store 中定義了一個狀態(tài) users,初始為空數(shù)組。
  • getters:定義了一個 count getter,它返回 users 數(shù)組的長度。
  • actions:定義了一個 addUser action,它接受一個用戶對象并將其添加到 users 數(shù)組中。
  • 在組件中使用:在組件的 <script setup> 塊中,通過調(diào)用 useUserStore 來獲取 Store 實例,并使用 computed 來創(chuàng)建響應(yīng)式的 usersuserCount
  • 添加用戶:定義了一個 addNewUser 函數(shù),當(dāng)按鈕被點擊時,調(diào)用 store.addUser 來添加新用戶。

以上案例展示了如何在 Pinia 中創(chuàng)建和管理狀態(tài),以及如何在 Vue 組件中使用 Store。通過這種方式,你可以集中管理狀態(tài),使得狀態(tài)邏輯更加清晰和可維護。

2. defineStore()

defineStore() 是 Pinia 中用于定義 Store 的函數(shù)。它允許你以聲明式的方式創(chuàng)建一個狀態(tài)管理單元,這個單元可以包含狀態(tài)(state)、獲取器(getters)、動作(actions)等。defineStore() 函數(shù)接受一個唯一的 ID 和一個配置對象,配置對象中可以定義 state、getters、actions 等屬性。

案例實現(xiàn)

下面是一個使用 defineStore() 創(chuàng)建 Store 的步驟解析,包括代碼示例:

步驟 1: 導(dǎo)入 defineStore

首先,需要從 Pinia 導(dǎo)入 defineStore 函數(shù)。

import { defineStore } from 'pinia'

步驟 2: 定義 Store

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

export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] // 購物車初始狀態(tài)為空數(shù)組
  }),
  getters: {
    // 計算屬性,返回購物車中商品的總數(shù)量
    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) {
        // 如果商品已存在,則增加數(shù)量
        this.items[index].quantity += item.quantity
      } else {
        // 否則,添加新商品
        this.items.push(item)
      }
    },
    // 清空購物車的動作
    clearCart() {
      this.items = []
    }
  }
})

步驟 3: 在組件中使用 Store

在 Vue 組件中,通過調(diào)用 useCartStore 來使用這個 Store。

<template>
  <div>
    <button @click="addItem">添加商品</button>
    <button @click="clearCart">清空購物車</button>
    <p>商品總數(shù): {{ itemCount }}</p>
    <ul>
      <li v-for="item in cartItems" :key="item.id">
        {{ item.name }} - 數(shù)量: {{ 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>

代碼解析

  • 導(dǎo)入 defineStore:從 Pinia 導(dǎo)入 defineStore 函數(shù)。
  • 定義 useCartStore:創(chuàng)建一個名為 useCartStore 的函數(shù),它返回一個配置好的 Store 對象。
  • state:在 Store 中定義了一個狀態(tài) items,初始為空數(shù)組,用于存儲購物車中的商品。
  • getters:定義了一個 itemCount getter,它通過遍歷 items 數(shù)組并累加每個商品的 quantity 來計算總數(shù)量。
  • actions:定義了 addItemclearCart 兩個 actions。addItem 用于向購物車添加商品,如果商品已存在則增加其數(shù)量;clearCart 用于清空購物車。
  • 在組件中使用:在組件的 <script setup> 塊中,通過調(diào)用 useCartStore 來獲取 Store 實例,并使用 computed 來創(chuàng)建響應(yīng)式的 cartItemsitemCount
  • 添加和清空商品:定義了 addItemclearCart 函數(shù),分別用于添加商品和清空購物車。

使用 defineStore() 創(chuàng)建一個包含狀態(tài)、獲取器和動作的 Store,并在 Vue 組件中使用這個 Store 來管理購物車的狀態(tài)。通過這種方式,你可以將狀態(tài)邏輯封裝在 Store 中,使得組件更加簡潔和易于管理。

3. reactive

reactive() 是 Vue 3 的 Composition API 中的一個函數(shù),它用于創(chuàng)建響應(yīng)式的狀態(tài)對象。當(dāng)使用 reactive() 創(chuàng)建一個對象后,Vue 會追蹤這個對象中屬性的讀取和修改,并且在數(shù)據(jù)變化時通知依賴于這些數(shù)據(jù)的組件重新渲染。

Pinia 與 Vue 的響應(yīng)式系統(tǒng)緊密集成,reactive() 通常在定義 Store 的狀態(tài)時使用。在 Pinia 中,狀態(tài)(state)是一個通過 reactive() 創(chuàng)建的響應(yīng)式對象,因此任何對狀態(tài)的修改都會自動觸發(fā)與該狀態(tài)相關(guān)的組件更新。

案例實現(xiàn)

下面是一個使用 reactive() 來創(chuàng)建響應(yīng)式狀態(tài)的步驟解析:

步驟 1: 導(dǎo)入 reactive

首先,需要從 Vue 導(dǎo)入 reactive 函數(shù)。

import { reactive } from 'vue'

步驟 2: 使用 reactive 創(chuàng)建狀態(tài)

使用 reactive() 函數(shù)來創(chuàng)建一個響應(yīng)式的狀態(tài)對象。

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

步驟 3: 在 Pinia Store 中使用 reactive 狀態(tài)

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

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 組件中,通過調(diào)用 useMyStore 來使用這個 Store,并訪問響應(yīng)式狀態(tài)。

<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>

代碼解析

  • 導(dǎo)入 reactive:從 Vue 導(dǎo)入 reactive 函數(shù)。
  • 創(chuàng)建響應(yīng)式狀態(tài):使用 reactive() 創(chuàng)建一個包含 countmessage 的響應(yīng)式狀態(tài)對象。
  • 在 Pinia Store 中使用 reactive:在 defineStore()state 函數(shù)中返回一個 reactive() 對象,這樣 Pinia 就可以管理這個狀態(tài)的響應(yīng)性。
  • 在組件中使用:在組件的 <script setup> 塊中,通過調(diào)用 useMyStore 來獲取 Store 實例。使用 computed 來確保訪問狀態(tài)時保持響應(yīng)性。
  • 修改狀態(tài):定義了一個 increment 函數(shù),當(dāng)按鈕被點擊時,直接修改 store.state.count,這會觸發(fā)組件的更新。

通過這種方式,你可以確保狀態(tài)的任何變化都會自動傳播到使用這些狀態(tài)的組件中,實現(xiàn)響應(yīng)式的數(shù)據(jù)流,你get到了嗎。

4. Devtools 支持

Vue Devtools 是一個瀏覽器擴展,它為開發(fā) Vue 應(yīng)用提供了強大的調(diào)試支持。對于 Pinia 來說,Devtools 支持意味著你可以在開發(fā)過程中更直觀地查看和操作應(yīng)用的狀態(tài)。

Pinia 與 Vue Devtools 集成,提供了以下功能:

  • 狀態(tài)查看:可以在 Devtools 中查看所有 Pinia Store 的狀態(tài)。
  • 時間旅行:回溯狀態(tài)的歷史,查看狀態(tài)的變化過程。
  • 動作追蹤:記錄和展示 Store 中 actions 的調(diào)用歷史,包括參數(shù)和執(zhí)行時間。
  • 狀態(tài)修改:允許你在 Devtools 中直接修改狀態(tài),這些修改會實時反映到應(yīng)用中。
  • 持久化狀態(tài):在開發(fā)過程中保持狀態(tài)不變,即使頁面刷新或組件重新渲染。

案例實現(xiàn)

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

步驟 1: 安裝 Vue Devtools

首先,確保你已經(jīng)安裝了 Vue Devtools 瀏覽器擴展。你可以從 Chrome Web Store 或 Firefox Add-ons 等地方安裝。

步驟 2: 創(chuàng)建 Pinia Store

創(chuàng)建一個 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 應(yīng)用中使用 Pinia

在你的 Vue 應(yīng)用中創(chuàng)建 Pinia 實例,并在應(yīng)用啟動時使用它。

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,并執(zhí)行一些狀態(tài)更改的動作。

<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 調(diào)試

  • 打開瀏覽器的開發(fā)者工具。
  • 切換到 Vue Devtools 面板。
  • 在“Components”或“Store”標簽頁中,你應(yīng)該能看到你的 Pinia Store。
  • 展開 Store,查看 state、getters 和 actions。
  • 點擊 actions,你可以看到它們的調(diào)用歷史和參數(shù)。
  • 直接在 Devtools 中修改 state 的值,看應(yīng)用如何響應(yīng)這些變化。

代碼過程步驟解析

  • 安裝 Devtools:確保瀏覽器擴展已安裝。
  • 創(chuàng)建 Store:使用 defineStore 創(chuàng)建一個包含 state、getters 和 actions 的 Pinia Store。
  • 應(yīng)用配置:在應(yīng)用啟動時創(chuàng)建 Pinia 實例并使用它。
  • 組件使用:在組件中通過調(diào)用 Store 函數(shù)來獲取 Store 實例,并使用 computed 屬性來保持響應(yīng)性。
  • 調(diào)試:使用 Vue Devtools 查看和修改狀態(tài),追蹤 actions。

利用 Vue Devtools 提供的功能來調(diào)試使用 Pinia 管理狀態(tài)的 Vue 應(yīng)用,感覺是不是挺爽。

5. 插件系統(tǒng)

Pinia 的插件系統(tǒng)允許開發(fā)者擴展 Pinia 的功能。插件可以訪問 Pinia 的 Store 創(chuàng)建過程,可以執(zhí)行以下操作:

  • 在 Store 創(chuàng)建之前或之后執(zhí)行自定義邏輯。
  • 攔截 Store 的 state、getters、actions 等屬性。
  • 向 Store 添加自定義屬性或方法。
  • 處理 Store 的銷毀邏輯。

Pinia 插件通常在創(chuàng)建 Pinia 實例時注冊,然后 Pinia 會將插件應(yīng)用到每個創(chuàng)建的 Store 上。

案例實現(xiàn)

下面是一個創(chuàng)建和使用 Pinia 插件的步驟解析,包括代碼示例:

步驟 1: 定義插件

首先,定義一個插件函數(shù),該函數(shù)接收 Pinia 的實例作為參數(shù)。

function myPiniaPlugin(pinia) {
  // 插件邏輯
}

步驟 2: 插件邏輯

在插件函數(shù)內(nèi)部,可以訪問 Pinia 的 store 對象,并對其進行操作。

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

步驟 3: 創(chuàng)建 Pinia 實例并使用插件

創(chuàng)建 Pinia 實例時,使用 use 方法注冊插件。

import { createPinia } from 'pinia'


const pinia = createPinia().use(myPiniaPlugin)

步驟 4: 創(chuàng)建 Store

定義一個 Store,使用 defineStore 函數(shù)。

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!

代碼過程步驟解析

  • 定義插件:創(chuàng)建一個函數(shù),該函數(shù)接收 Pinia 實例并定義插件邏輯。
  • 插件邏輯:在插件函數(shù)內(nèi)部,使用 pinia.use 方法注冊一個回調(diào),該回調(diào)接收每個 Store 并可以對其進行操作。
  • 注冊插件:在創(chuàng)建 Pinia 實例時,通過 .use() 方法注冊插件。
  • 創(chuàng)建 Store:使用 defineStore 定義 Store,包括 state、getters、actions。
  • 使用 Store:在組件中使用 Store,并利用 computed 屬性保持響應(yīng)性。
  • 訪問插件屬性:在組件的模板或腳本中,訪問插件添加到 Store 的自定義屬性。

記住這一點,開發(fā)者需要添加自定義邏輯和屬性,通過Pinia 插件系統(tǒng)就 OK。

6. TypeScript 支持

Pinia 為 TypeScript 用戶提供了一流的支持,確保類型安全和開發(fā)體驗。Pinia 的 TypeScript 支持主要體現(xiàn)在以下幾個方面:

  1. 類型推斷:Pinia 利用 TypeScript 的高級類型系統(tǒng)來推斷 Store 中的狀態(tài)、getters 和 actions 的類型。
  2. 類型聲明:Pinia 提供了類型聲明文件(.d.ts),確保 Pinia API 在 TypeScript 項目中的類型正確性。
  3. 自動補全:在 TypeScript 環(huán)境中,編輯器可以提供自動補全功能,幫助開發(fā)者快速編寫代碼。
  4. 類型守衛(wèi):Pinia 與 TypeScript 配合使用時,可以利用類型守衛(wèi)來確保對 Store 屬性的訪問是安全的。

案例實現(xiàn)

下面是一個使用 TypeScript 與 Pinia 結(jié)合使用的步驟解析,包括代碼示例:

步驟 1: 設(shè)置 TypeScript 環(huán)境

確保你的項目已經(jīng)配置了 TypeScript,并且安裝了必要的類型聲明文件。

npm install typescript @vue/compiler-sfc

步驟 2: 定義 Store 使用 TypeScript

使用 TypeScript 的類型定義來創(chuàng)建 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: 利用類型守衛(wèi)

使用類型守衛(wèi)來確保對 Store 屬性的訪問是安全的。

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

代碼過程步驟解析

  • 配置 TypeScript:確保項目中安裝了 TypeScript 及其類型聲明文件。
  • 定義 Store 類型:使用 TypeScript 的接口(interface)來定義 Store 的狀態(tài)類型。
  • 創(chuàng)建 Store:使用 defineStore 并傳入類型化的 state 函數(shù),以及聲明了返回類型的 getters 和 actions。
  • 組件中使用 Store:在組件中使用 TypeScript 來確保訪問 Store 屬性的類型安全。
  • 類型守衛(wèi):使用 TypeScript 的 hasOwnProperty 方法和類型守衛(wèi)來安全地訪問 Store 的屬性。

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

7. SSR 支持

服務(wù)器端渲染(SSR)是一種將網(wǎng)站頁面在服務(wù)器上生成并發(fā)送給客戶端的技術(shù)。對于狀態(tài)管理庫來說,SSR 支持意味著可以在服務(wù)器上初始化和操作狀態(tài),然后將狀態(tài)序列化后發(fā)送到客戶端,客戶端再將這些狀態(tài)恢復(fù)以保持與服務(wù)器端相同的狀態(tài)。

Pinia 對 SSR 的支持主要體現(xiàn)在以下幾個方面:

  1. 狀態(tài)序列化:Pinia 允許將狀態(tài)(state)序列化成 JSON 字符串,以便在服務(wù)器和客戶端之間傳輸。
  2. 狀態(tài)恢復(fù):客戶端可以接收服務(wù)器端的狀態(tài),并將其恢復(fù)到對應(yīng)的 Store 中。
  3. 無狀態(tài)的 Store 定義:Pinia 的 Store 定義是無狀態(tài)的,這意味著在服務(wù)器端和客戶端端都可以重新創(chuàng)建 Store。
  4. 與 Vue SSR 的集成:Pinia 可以與 Vue 的 SSR 系統(tǒng)集成,確保在服務(wù)器端預(yù)渲染組件時使用正確的狀態(tài)。

案例實現(xiàn)

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

步驟 1: 定義 Store

首先,定義一個 Pinia Store。

import { defineStore } from 'pinia'


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

步驟 2: 在服務(wù)器端創(chuàng)建和序列化狀態(tài)

在服務(wù)器端,創(chuàng)建 Store 實例并初始化狀態(tài),然后將狀態(tài)序列化。

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


const pinia = createPinia()


// 模擬從數(shù)據(jù)庫獲取初始狀態(tài)
const initialState = { count: 10 }


// 創(chuàng)建 Store 實例并設(shè)置初始狀態(tài)
const store = useMyStore(pinia)
store.$state.count = initialState.count


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

步驟 3: 在客戶端恢復(fù)狀態(tài)

在客戶端,接收服務(wù)器端發(fā)送的狀態(tài),然后恢復(fù)到對應(yīng)的 Store 中。

// client.js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue' // Vue 應(yīng)用的根組件
import useMyStore from '@/stores/myStore'


const pinia = createPinia()


// 假設(shè)從服務(wù)器接收的狀態(tài)如下
const stateFromServer = JSON.parse(/* state serialized from server */)


// 創(chuàng)建 Store 實例并恢復(fù)狀態(tài)
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。
  • 服務(wù)器端創(chuàng)建和序列化:在服務(wù)器端,創(chuàng)建 Store 實例,設(shè)置初始狀態(tài),并使用 JSON.stringify 序列化狀態(tài)。
  • 客戶端恢復(fù)狀態(tài):在客戶端,解析服務(wù)器端發(fā)送的狀態(tài)字符串,并恢復(fù)到 Store 的 $state 中。
  • 組件中使用 Store:在 Vue 組件中,通過調(diào)用 Store 函數(shù)獲取 Store 實例,并使用 computed 屬性來訪問狀態(tài)。

一句話,Pinia支持SSR有助于提高應(yīng)用的初始加載性能和SEO優(yōu)化。

8. 映射輔助函數(shù)

在 Pinia 中,映射輔助函數(shù)用于將 Store 中的狀態(tài)(state)、獲取器(getters)、動作(actions)映射到組件的計算屬性(computed properties)、方法(methods)或響應(yīng)式屬性上。這些輔助函數(shù)提供了一種便捷的方式來使用 Store,而無需在每個組件中重復(fù)編寫相同的代碼。

Pinia 的映射輔助函數(shù)主要包括:

  • mapState:將 Store 中的狀態(tài)映射為組件的計算屬性。
  • mapGetters:將 Store 中的獲取器映射為組件的計算屬性。
  • mapActions:將 Store 中的動作映射為組件的方法。

案例實現(xiàn)

下面是一個使用 Pinia 映射輔助函數(shù)的步驟解析,包括代碼示例:

步驟 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: 使用映射輔助函數(shù)

在組件中,使用 mapState、mapGettersmapActions 將 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 映射狀態(tài)
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 定義一個包含狀態(tài)、獲取器和動作的 Pinia Store。
  • 使用映射輔助函數(shù)
    • mapState:將 items 狀態(tài)映射為組件的計算屬性。
    • mapGetters:將 itemCount 獲取器映射為組件的計算屬性。
    • mapActions:將 addItem 動作映射為組件的方法。
  • 模板中使用:在模板中,使用映射的計算屬性 itemCount 來顯示項目數(shù)量,使用映射的方法 addItem 來添加新項目。

使用映射輔助函數(shù),Pinia 可以讓開發(fā)者以聲明式的方式在組件中使用 Store 的狀態(tài)和行為,從而減少樣板代碼并提高組件的可讀性和可維護性。此外,這些輔助函數(shù)還有助于保持響應(yīng)性,確保當(dāng) Store 中的狀態(tài)變化時,組件能夠自動更新。

最后

不得不說,Pinia 提供了一種靈活且高效的方式來管理 Vue 應(yīng)用的狀態(tài),無論是在單頁應(yīng)用還是服務(wù)器端渲染的場景下,都有出色的表現(xiàn),寫完收工,歡迎關(guān)注威哥愛編程,一起走全棧之路。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號