Pinia 终极指南:Vue 3 的现代化状态管理
1. 为什么选择 Pinia?
Pinia 是 Vue 3 官方推荐的状态管理库,相比 Vuex 具有以下优势:
- 更简单的 API:去除了
mutations
,只有state
、getters
、actions
- 完整的 TypeScript 支持
- 模块化设计,无需嵌套模块
- 支持 Composition API 和 Options API
- DevTools 集成,方便调试
2. 初始化 Pinia
(1) 安装
npm install pinia
(2) 在 Vue 应用中使用
// 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')
3. 核心概念
(1) 定义 Store
// stores/counter.ts
import { defineStore } from 'pinia'
// 使用 Options 风格
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
// 使用 Composition 风格
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
(2) 在组件中使用 Store
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<div>Count: {{ counter.count }}</div>
<div>Double: {{ counter.doubleCount }}</div>
<button @click="counter.increment()">+1</button>
</template>
4. 高级用法
(1) 状态持久化
npm install pinia-plugin-persistedstate
// main.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
// 在 store 中启用
export const useUserStore = defineStore('user', {
state: () => ({ name: '' }),
persist: true
})
(2) 重置 Store 状态
const userStore = useUserStore()
userStore.$reset() // 重置为初始状态
(3) 订阅状态变化
userStore.$subscribe((mutation, state) => {
console.log('状态变化:', mutation.type, state)
})
(4) 组合多个 Store
import { useUserStore } from './user'
import { useCartStore } from './cart'
export const useCombinedStore = () => {
return {
user: useUserStore(),
cart: useCartStore()
}
}
5. TypeScript 最佳实践
(1) 严格类型定义
interface UserState {
name: string
age: number
email?: string
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
name: '',
age: 0
}),
getters: {
isAdult: (state) => state.age >= 18
}
})
(2) 类型安全的 Actions
actions: {
async fetchUser(id: number): Promise<User> {
const user = await api.fetchUser(id)
this.name = user.name
return user
}
}
6. 与 Vue Router 集成
// 在导航守卫中使用 store
router.beforeEach((to) => {
const userStore = useUserStore()
if (to.meta.requiresAuth && !userStore.isLoggedIn) {
return '/login'
}
})
7. 性能优化
(1) 解构保持响应式
import { storeToRefs } from 'pinia'
const counter = useCounterStore()
const { count, doubleCount } = storeToRefs(counter) // 保持响应式
(2) 按需导入 Store
// 只在需要时加载 store
const userStore = useUserStore()
8. 常见问题
Q1: 如何热更新 Store?
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
}
Q2: 如何测试 Store?
import { setActivePinia, createPinia } from 'pinia'
import { useCounterStore } from '@/stores/counter'
beforeEach(() => {
setActivePinia(createPinia())
})
test('increment action', () => {
const counter = useCounterStore()
counter.increment()
expect(counter.count).toBe(1)
})
9. 总结
- Pinia 是 Vue 3 的轻量级、类型安全的状态管理方案
- 比 Vuex 更简单,更适合 TypeScript
- 支持持久化、模块化、DevTools
- 完美配合 Composition API
官方推荐组合:
🔥 Vue 3
+ Pinia
+ TypeScript
= 终极开发体验
进一步学习: