最近改一个vue2+vuex的项目,发现很不方便,学过pinia感觉方便很多
首先,什么是Vuex和pinia,他们是 vue.js生态中的 状态管理 工具
Vuex的四个核心概念 : state (数据)、getters (计算属性)、mutations (修改state数据)、actions(方法)
const store = new Vuex.Store({
state: {
count: 0,
user: null
},
getters: {
doubleCount(state) {
return state.count * 2
}
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
async increment({ commit }) {
await someAsyncTask()
commit('increment')
}
}
})
Vuex挂载到vue示例上
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({...})
Vuex设计mutations是为了:
- 确保状态变更的可追踪性(通过devtools)
- 强制同步操作,使状态变更可预测
- 实现"单向数据流"的设计模式
人话版: 为了标记是谁改了他 如何使用Vuex
// 在组件中使用 state
this.$store.state.count
// 使用 getters
this.$store.getters.doubleCount
// 使用 mutations(同步修改state)
this.$store.commit('increment')
this.$store.commit('increment', 10) // 传参
// 使用 actions(异步操作)
this.$store.dispatch('increment')
pinia的三个核心概念(舍弃了mutations): state (数据)、getters (计算属性)actions(方法)
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({
items: [],
total: 0
}),
getters: {
itemCount(state) {
return state.items.length
}
},
actions: {
async addItem(product) {
const stock = await checkStock(product.id)
if (stock > 0) {
this.items.push({
...product,
quantity: 1
})
}
}
}
})
pinia安装到vue实例上
import { createPinia } from 'pinia'
const pinia = createPinia()
app.use(pinia)
pinia舍弃掉mutations的原因
- Pinia简化了API设计
- actions可以直接修改state
- 移除mutations减少了代码层级,提高了开发体验
- 仍然保持状态变更的可追踪性
人话版: 因为vue3的响应式设计,他可以通过调用栈来得知谁修改了 如何去使用 pinia
<script setup>
import { useCartStore } from '@/stores/cart'
const cart = useCartStore()
console.log(cart.items) // state
console.log(cart.totalPrice) // getter
cart.addItem(product) // action
</script>
pinia和vuex的区别
- 代码量 - Pinia代码更简洁,去掉了mutations
- TypeScript的支持 - Pinia天然支持TypeScript,类型推断更好
- 模块化设计
- Vuex:需要手动配置modules,使用命名空间
- Pinia:每个store独立,天然模块化
- 挂载方式
- Vuex:必须挂载到Vue实例(
Vue.use(Vuex)) - Pinia:按需导入,不需要挂载到实例
- Vuex:必须挂载到Vue实例(
- 状态修改
- Vuex:state → mutation → action(三层)
- Pinia:state → action(两层,action可直接修改state)
- Devtools支持 - 两者都支持,但Pinia的追踪更直观
- Vue版本支持
- Vuex:主要用于Vue 2
- Pinia:Vue 3官方推荐,也有Vue 2版本
- State访问
- Vuex:
this.$store.state.xxx - Pinia:直接
store.xxx,更符合直觉
- Vuex:
TypeScript支持示例
// TypeScript 示例
interface User {
id: number
name: string
}
export const useUserStore = defineStore('user', {
state: () => ({
user: null as User | null,
isLoading: false
}),
getters: {
userName(): string {
return this.user?.name || 'Guest'
}
}
})
总结:Pinia作为Vuex的继任者,在API设计、开发体验和TypeScript支持上都有显著提升。新项目建议优先选择Pinia。