在 Vue.js 生態系統中,Pinia 是目前官方推薦的狀態管理函式庫。不過,當我們透過 Pinia 儲存資料時,這些資料究竟放在哪裡?本文拆解 Pinia 的運作原理,以及它如何處理資料儲存。
Pinia 的核心概念
Pinia 把應用程式的狀態切成獨立的「store」,每個 store 負責管理一塊特定的狀態。這種設計讓狀態管理更模組化,也比較容易維護。
定義一個 store 的基本寫法:
1 | import { defineStore } from 'pinia' |
記憶體中的資料儲存
Pinia 的資料主要放在應用程式的記憶體裡,底層是 Vue 的響應式系統。
- 響應式物件:store 的
state在底層是用ref()包裹、再透過reactive()展開。這讓所有依賴該狀態的元件在資料變動時自動重新渲染,不需要手動觸發。 - JavaScript 執行環境:響應式物件存在 JavaScript 執行環境中——客戶端應用放在瀏覽器記憶體,伺服器端渲染(SSR)則放在伺服器記憶體,頁面重整或 tab 關閉後就消失。
持久化儲存
預設情況下 Pinia 不會把資料寫到任何持久化位置,頁面重整就歸零。需要跨重整保留資料時,有幾種做法:
1. localStorage / sessionStorage
直接在 action 裡手動讀寫,或用 pinia-plugin-persistedstate 自動化這個流程。
手動寫法
1 | export const useUserStore = defineStore('user', { |
使用 pinia-plugin-persistedstate
1 | npm install pinia-plugin-persistedstate |
1 | // main.js |
1 | export const useUserStore = defineStore('user', { |
也可以細調要持久化哪些欄位,或改用 sessionStorage:
1 | persist: { |
2. IndexedDB
適合儲存量較大的客戶端資料(例如離線資料集)。需注意 IndexedDB 是非同步 API,無法直接插入 pinia-plugin-persistedstate(後者要求同步的 getItem/setItem 介面)。實務上通常透過 localForage 包一層同步介面來銜接。
3. 伺服器端儲存
需要跨裝置或跨工作階段保留的資料,應透過 API 寫入資料庫,Pinia 只扮演客戶端快取的角色。
資料流動過程
1 | 應用啟動 |
小結
Pinia 的狀態存在記憶體裡,以響應式物件的形式跟著 Vue 的渲染週期走。頁面重整就消失是預設行為,不是 bug——需要持久化時,pinia-plugin-persistedstate 是最直接的方案,配合 pick 選項可以只持久化必要的欄位,避免把敏感資料(如完整 token payload)無意間全寫進 localStorage。




