Redux、Vuex、Pinia 之间的区别

这三个库不是凭空冒出来的。它们要解决的,是同一个根本问题:

当很多组件都要读写同一份"全局状态"时,怎么既不让代码乱成一团,又保证状态的变化可追踪、可预测?

想象一间开放式办公室里有一块公共白板。谁都可以看,谁都可以改。如果不立规矩,三个人同时改、你不知道最后那行字是谁写的、为什么改——bug 就来了。

用 props 和事件也能传状态,但当组件树很深、要共享状态的组件离得很远时,一层层往下传(prop drilling)会让人崩溃。于是大家把状态提到一个"全局仓库"里。

但全局可变状态本身是个危险源。这三个库,本质上是三套不同的"白板使用守则"。

Redux:规矩最严的那套守则

核心三条:

  1. 单一数据源:整个应用的状态是一棵树,装在一个 store 里。
  2. 状态只读:不能直接改。想改,就发一个 action(一个描述"发生了什么"的普通对象)。
  3. 用纯函数改状态:reducer 接收 (旧状态, action),返回状态。它不修改入参,也不搞副作用。
import { createStore } from 'redux'

// reducer:纯函数,接收 (旧state, action) 返回新 state
function counter(state = { value: 0 }, action) {
  switch (action.type) {
    case 'incremented':
      return { ...state, value: state.value + 1 } // 返回新对象,不改动旧的
    default:
      return state
  }
}

// store 由 createStore 创建:装着整棵 state 树,暴露 dispatch / getState / subscribe
const store = createStore(counter)
store.getState()                   // { value: 0 }
store.dispatch({ type: 'incremented' })
store.getState()                   // { value: 1 }

异步怎么办?reducer 必须是纯函数,不能塞异步。所以异步逻辑放进 thunk / saga 这类 middleware,等数据回来了再 dispatch 一个普通 action。

关键点:Redux 内核本身跟框架无关。它能在 React、Vue、Angular、甚至原生 JS 里用。真正把它接进 React 的是 react-redux

现代写法:官方现在推荐 Redux Toolkit (RTK)。它用 Immer 库,让你写出"像是直接改"的代码,底层其实还是生成不可变的新状态:

const counter = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    incremented: (state) => { state.value += 1 } // 看着像改,实际是 Immer 生成新状态
  }
})

// createSlice 只产出 reducer 和 action,还没造 store。
// 真正创建 store 用的是 configureStore(内部仍是 createStore,但默认挂好 thunk、DevTools、reducer 合并)
const store = configureStore({ reducer: counter })

这套严格规矩换来了什么?状态变化完全可预测、易测试,而且天然支持"时间旅行调试"——因为每一步都是"旧状态 + action → 新状态",DevTools 能把整条历史重放。

Vuex:给 Vue 量身定做的车间

Vuex 同样管全局状态,但它长在 Vue 的响应式系统上,概念比 Redux 多一层:

  • state:状态
  • getters:基于 state 计算出来的派生值(类似 computed)
  • mutations唯一能改 state 的地方,且必须是同步的
  • actions:可以异步,但不能直接改 state,只能 commit 一个 mutation
const store = createStore({
  state: () => ({ count: 0 }),
  mutations: {
    INCREMENT(state) { state.count++ } // 同步、唯一的改法
  },
  actions: {
    increment({ commit }) { commit('INCREMENT') } // 异步逻辑在这里,改状态还得 commit
  }
})

为什么要把"改状态"拆成 mutation 和 action 两步?因为 mutation 强制同步,DevTools 就能把每一次状态变更都记录成一个清晰的快照,支持时间旅行。这是 Vuex 当初的设计取舍:用一点样板代码,换调试可见性

Pinia:把车间里多余的脚手架拆了

Pinia 一开始就是按"Vuex 5 该长什么样"探索出来的,现在它成了 Vue 的官方推荐,Vuex 进入维护模式(只修 bug,不加新功能)。

它做的最关键的一刀:砍掉 mutations

export const useCounter = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: { double: (s) => s.count * 2 },
  actions: {
    increment() { this.count++ },              // 同步直接改
    async load() { this.count = await api() }  // 异步也能直接改
  }
})

变化在哪:

  • 概念从四个变三个:state、getters、actions。action 把 Vuex 里 mutation 和 action 的活儿全干了。
  • 直接改状态也会被追踪:Pinia 跑在 Vue 响应式系统上,状态的每一次变动都被记录下来,DevTools 照样能时间旅行——所以"去掉 mutation 会丢失可追溯性"这个担心不成立。真正去掉的,只是"强制同步修改"那条约束,而那条约束主要服务于 DevTools,不是服务于你的业务逻辑。
  • 多个扁平 store,不再是嵌套 module:每个 store 独立、可摇树优化,不用再写 namespaced: true 那套命名空间仪式。
  • TypeScript 一等公民:类型从 store 定义自动推断,不用像 Vuex 那样手动做类型增强。
  • 两种写法:Options(像 Vuex,好迁移)和 Setup(直接用语法的 ref / computed,最灵活)。

一张表看清差别

维度 Redux (RTK) Vuex 4 Pinia
适用框架 框架无关(常配 React) Vue Vue
改状态的入口 dispatch action → reducer commit mutation(同步唯一入口) action 里直接改 / $patch
异步放哪 middleware (thunk/saga) actions actions
状态是否可变 不可变(RTK 用 Immer 伪装可改) 可变(mutation 里直接改) 可变(action 里直接改)
store 结构 单一 store + slice 单一 store + 嵌套 module 多个扁平 store
TypeScript 需配置,RTK 体验好 手动类型增强 开箱推断
时间旅行调试
当前地位 React 生态主流 维护模式 Vue 官方推荐

怎么选?

  • React 项目 / 要框架无关:Redux 仍是稳妥主流。它规矩多、样板多,但换来最强的可预测性和最庞大的生态(RTK Query、丰富 middleware、成熟的 DevTools)。新项目直接用 Redux Toolkit,别再手写 switch/action-type 那套老写法。
  • 新 Vue 3 项目:默认 Pinia。官方推荐、代码更少、TS 体验最好。
  • 老 Vue 2/3 项目已经在用 Vuex:不用急着迁。Vuex 还能用;只有当你本来就在做 Vue 3 升级时,才值得顺手迁到 Pinia。两者可并存,逐步迁移。

一个常见的误解值得点破:"直接改状态"不等于"失控"。Redux 的不可变更新,价值在于用引用相等做廉价的变化检测、以及支持时间旅行;Vuex 的 mutation,价值在于强制同步以便 DevTools 记录。Pinia 借 Vue 的响应式系统,在不强制不可变、不强制 mutation 的前提下,照样拿到了可追溯性。所以选哪个,不是"谁更严谨"的问题,而是"你的框架和团队更需要哪套规矩"的问题。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容