Vue 3 Pinia 状态管理完全指南

Sarah Wong | 2026-08-27T20:54:33 | JavaScript, Frontend

从 Vuex 迁移到 Pinia,详解 defineStore、组合式写法、持久化插件和 SSR 适配方案。

# Vue 3 Pinia 状态管理完全指南 ## 为什么选择 Pinia? Pinia 是 Vue 官方推荐的状态管理库,相比 Vuex 有三大优势: 1. 完整的 TypeScript 支持 2. 去掉了 mutations,只有 state、getters、actions 3. 模块化设计,无需嵌套模块 ## 安装与配置 ```bash npm install pinia ``` ```typescript // main.ts import { createApp } from 'vue'; import { createPinia } from 'pinia'; import App from './App.vue'; const app = createApp(App); app.use(createPinia()); app.mount('#app'); ``` ## 定义 Store(选项式) ```typescript // stores/user.ts import { defineStore } from 'pinia'; export const useUserStore = defineStore('user', { state: () => ({ name: '', email: '', token: '', isLoggedIn: false, }), getters: { displayName(state) { return state.name || state.email.split('@')[0]; }, }, actions: { async login(account, password) { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ account: account, password: password }), }); const data = await res.json(); this.name = data.name; this.email = data.email; this.token = data.token; this.isLoggedIn = true; }, logout() { this.$reset(); }, }, }); ``` ## 定义 Store(组合式,推荐) ```typescript // stores/cart.ts import { ref, computed } from 'vue'; import { defineStore } from 'pinia'; export const useCartStore = defineStore('cart', () => { const items = ref([]); const totalPrice = computed(() => items.value.reduce((sum, item) => sum + item.price * item.qty, 0) ); const itemCount = computed(() => items.value.reduce((sum, item) => sum + item.qty, 0) ); function addItem(product) { const existing = items.value.find((i) => i.id === product.id); if (existing) { existing.qty += 1; } else { items.value.push({ ...product, qty: 1 }); } } function removeItem(productId) { items.value = items.value.filter((i) => i.id !== productId); } return { items, totalPrice, itemCount, addItem, removeItem }; }); ``` ## 持久化插件 ```bash npm install pinia-plugin-persistedstate ``` ```typescript import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; const pinia = createPinia(); pinia.use(piniaPluginPersistedstate); // 在 store 中启用 export const useUserStore = defineStore('user', () => { // ... }, { persist: { key: 'user-store', storage: localStorage, pick: ['token', 'name'], // 只持久化指定字段 }, }); ``` ## 在组件中使用 ```vue import { useUserStore } from '@/stores/user'; import { storeToRefs } from 'pinia'; const userStore = useUserStore(); // storeToRefs 保持响应性 const { name, isLoggedIn } = storeToRefs(userStore); // actions 直接解构 const { login, logout } = userStore; ``` ## 注意事项 1. 不要直接解构 state,用 `storeToRefs` 2. 组合式写法更灵活,推荐新项目使用 3. Store 之间可以互相调用,但注意避免循环依赖

← Back to Blog