模式切换
Vuex 4 与 Pinia
Vuex 4 核心概念
Vuex 是 Vue 的官方状态管理库,采用集中式存储管理应用的所有组件的状态。
核心组成
概念 | 作用 | 示例 |
---|---|---|
State | 单一状态树,存储数据源 | state: { count: 0 } |
Getters | 从 state 派生的计算属性 | getters: { doubleCount: (state) => state.count * 2 } |
Mutations | 同步修改 state 的方法 | mutations: { increment(state) { state.count++ } } |
Actions | 提交 mutations,可包含异步操作 | actions: { asyncIncrement({ commit }) { setTimeout(() => commit('increment'), 1000) } } |
Modules | 将 store 分割成模块 | modules: { user: userModule } |
典型使用流程
javascript
// store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => commit('increment'), 1000)
}
},
getters: {
doubleCount: state => state.count * 2
}
})
// 组件中使用
import { useStore } from 'vuex'
export default {
setup() {
const store = useStore()
// 访问 state
console.log(store.state.count)
// 触发 mutation
store.commit('increment')
// 触发 action
store.dispatch('asyncIncrement')
// 使用 getter
console.log(store.getters.doubleCount)
return {}
}
}
优缺点
- 优点:
- 官方维护,稳定性高
- 严格的流程控制(mutations必须是同步)
- 缺点:
- 样板代码较多
- TypeScript 支持一般
- 模块嵌套复杂
Pinia 核心概念
Pinia 是 Vue 官方推荐的新一代状态管理库,相比 Vuex 更简单直观。
核心改进
- 去掉 mutations,只有 state/getters/actions
- 完整的 TypeScript 支持
- 更简洁的 API
- 支持组合式 API 和选项式 API
- 模块化设计开箱即用
核心组成
概念 | 作用 | 与 Vuex 对比 |
---|---|---|
State | 存储数据源 | 同 Vuex |
Getters | 计算属性 | 同 Vuex |
Actions | 同步/异步操作 | 合并了 Vuex 的 mutations 和 actions |
Stores | 独立的状态单元 | 替代 Vuex 的 modules,无需嵌套 |
典型使用流程
javascript
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
},
async asyncIncrement() {
setTimeout(() => this.increment(), 1000)
}
}
})
// 组件中使用
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
// 访问 state
console.log(counter.count)
// 调用 action
counter.increment()
counter.asyncIncrement()
// 使用 getter
console.log(counter.doubleCount)
// 直接修改 state (不推荐)
counter.count++
return {}
}
}
高级特性
组合式 Store
javascript
export const useUserStore = defineStore('user', () => {
const user = ref(null)
function login() {
// 登录逻辑
}
return { user, login }
})
插件系统
javascript
// 持久化插件示例
pinia.use(({ store }) => {
const saved = localStorage.getItem(store.$id)
if (saved) {
store.$patch(JSON.parse(saved))
}
store.$subscribe((mutation, state) => {
localStorage.setItem(store.$id, JSON.stringify(state))
})
})
优缺点
- 优点:
- 更简洁的 API
- 完美的 TypeScript 支持
- 自动代码分割
- 更轻量
- 缺点:
- 相对较新,生态还在成长
- 迁移成本(对已有 Vuex 项目)
Vuex 与 Pinia 对比
特性 | Vuex 4 | Pinia |
---|---|---|
API 复杂度 | 高(mutations/actions分离) | 低(只有 actions) |
TypeScript 支持 | 一般 | 优秀 |
代码组织 | 需要 modules | 天然模块化 |
体积 | 较大 | 更轻量 |
学习曲线 | 较陡峭 | 平缓 |
DevTools 支持 | 完善 | 完善 |
Vue 官方推荐 | 是(旧项目) | 是(新项目) |
迁移建议
- 新项目:直接使用 Pinia
- 已有 Vuex 项目:
- 小型项目:逐步迁移到 Pinia
- 大型项目:继续使用 Vuex,新功能用 Pinia
最佳实践
通用模式
- 将业务逻辑放在 store 中
- 组件只负责展示和触发 actions
- 复杂数据操作使用 getters
项目结构
src/
stores/
user.js # 用户相关状态
products.js # 产品相关状态
cart.js # 购物车状态
index.js # Pinia 初始化
TypeScript 增强
typescript
interface UserState {
name: string
age: number
}
export const useUserStore = defineStore('user', {
state: (): UserState => ({
name: '',
age: 0
})
})