• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
麦兜家园
优秀是一种习惯
博客园    首页    新随笔    联系   管理    订阅  订阅

vue3 中的pinia和vue2中的vuex的区别

一、先说结论:它俩到底啥关系?

打个比方:
  • Vuex 是 Vue 2 时代的"老管家",规矩多、流程复杂,但是很全能。
  • Pinia 是 Vue 3 时代的"新管家",是 Vue 官方现在推荐的默认状态管理方案(Vuex 4 虽然能用,但官方态度已经是"新项目用 Pinia")。
一句话总结核心差别:Pinia 把 Vuex 里最繁琐的部分删掉了,剩下的都是精华。

二、核心概念:5 个变 3 个

这是两者最直观的区别。Vuex 一套流程要记 5 个概念,Pinia 只留 3 个:
概念
Vuex
Pinia
说明
state(数据)
✅
✅
状态数据,两边都有
getters(计算属性)
✅
✅
派生的数据,两边都有
mutations(同步修改)
✅
❌ 删掉了
Pinia 里不需要
actions(异步操作)
✅
✅
但 Pinia 的 actions 更强大
modules(模块)
✅
❌ 删掉了
Pinia 天然就是模块化的
最大的变化就是 mutations 没了。

三、最关键的改变:mutations 为什么被"开掉"了?

在 Vuex 里,改数据有一条铁律:
同步修改必须走 mutations,异步操作必须先走 actions,再在 actions 里 commit 给 mutations。
所以写一个异步改数据的操作,你要绕一大圈:
// ===== Vuex 写法:一改数据要过两道门 =====
// 1. mutations:只负责同步改
mutations: {
  setCount(state, n) {
    state.count = n
  }
},
// 2. actions:负责异步,再转交给 mutations
actions: {
  async fetchCount({ commit }) {
    const data = await api.get()
    commit('setCount', data)   // 转一道手
  }
}
// 3. 组件里调用
this.$store.dispatch('fetchCount')
而 Pinia 直接"一个 actions 搞定",同步异步都能直接改:
// ===== Pinia 写法:一步到位 =====
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    async fetchCount() {
      this.count = await api.get()   // 直接改,不转手
    }
  }
})
// 组件里调用
counterStore.fetchCount()
大白话解释:Vuex 是"改数据要先过两道安检",Pinia 是"直接改,但依然能追踪"。少了一道繁琐的流程,代码量直接减半,对新手友好太多。

四、模块化:从"套娃"到"自由"

这是第二个大差异。
Vuex 用 modules 嵌套,还要写 namespaced: true 来防止命名冲突,一旦模块多了就像套娃,找东西很费劲:
// ===== Vuex:要注册模块 + 命名空间 =====
export default new Vuex.Store({
  modules: {
    user: userModule,     // 得手动挂载
    cart: { namespaced: true, ... }  // 还得设命名空间
  }
})
// 组件里调用还要写全路径
this.$store.commit('cart/addItem', item)
Pinia 不需要 modules,每个 store 本身就是独立的"文件",谁要用谁引入,清爽自然:
// ===== Pinia:每个 store 自己独立,不用挂载 =====
// user.js
export const useUserStore = defineStore('user', { ... })
// cart.js
export const useCartStore = defineStore('cart', { ... })

// 组件里直接用
const userStore = useUserStore()
const cartStore = useCartStore()
大白话解释:Vuex 是"一个大柜子,所有东西塞进去,还要贴标签防止撞名";Pinia 是"每人一个独立抽屉,各自管各自",没有命名空间烦恼,代码更好维护。

五、TypeScript 支持:Pinia 完胜

这一点对工程化项目尤其重要。
  • Vuex 在 TS 下:要写一堆类型定义、namespace、模块类型,用起来很繁琐,经常要"类型体操"。
  • Pinia 在 TS 下:类型推断非常友好,几乎零配置,IDE 提示也准。它本身就用 TS 写的,天生为 TS 设计。
如果你是用 TS 写 Vue3 项目,Pinia 几乎是必然选择。

六、组件里怎么用:一个更顺手

Vuex 需要靠 this.$store 或者 useStore(),访问要带 state. / getters. 前缀,修改要 commit,异步要 dispatch,记的东西多:
// Vuex 组件里
this.$store.state.count
this.$store.getters.doubleCount
this.$store.commit('setCount', 10)
this.$store.dispatch('fetchCount')
Pinia 直接解构使用,跟操作普通对象一样,还专门提供了 storeToRefs 保持响应性:
// Pinia 组件里
const counterStore = useCounterStore()
const { count } = storeToRefs(counterStore)  // 保持响应式
counterStore.count = 10                       // 直接赋值修改
counterStore.fetchCount()

七、一张表速览所有区别

对比项
Vuex
Pinia
适用版本
Vue 2 / Vue 3(Vuex 4)
Vue 3(重点)
官方定位
旧版默认
当前官方推荐
核心概念
state/getters/mutations/actions/modules
state/getters/actions
mutations
必须有
已移除
异步改状态
actions → commit mutations
actions 直接改
模块化
modules 嵌套 + 命名空间
多 store 独立
TypeScript
支持但繁琐
原生友好
代码量
多
少(约少一半)
组合式 API
支持一般
完全适配
体积
较大
更轻量

八、我该选哪个?给个直接的建议

  • 新项目用 Vue3 → 直接用 Pinia,官方推荐,代码简洁,别再纠结。
  • 老项目用 Vue2 → 继续用 Vuex,没必要动,稳定为王。
  • 老项目从 Vue2 迁 Vue3 → 建议顺手迁到 Pinia,改动其实不大(主要是去掉 mutations、去掉 modules)。

九、一个比喻帮你记牢

把状态管理想象成管理家里的物品:
  • Vuex:所有东西放一个总仓库,拿东西要填"申请单"(commit)、要派人去取(dispatch),分门别类还得挂标签(namespaced)。规矩多,但把安全做到了极致。
  • Pinia:每个房间自己管自己的东西,开门就能拿,放下就能改,但记录依然清楚。简单直接,又不失控。
一句话:Vuex 教会了我们"怎么管状态",Pinia 让我们"更轻松地管状态"。 如果是从零开始,直接拥抱 Pinia 就对了。

 

posted on 2026-09-30 15:46  麦兜家园  阅读(13)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3