mobx、redux 和 vuex 都是用于管理复杂前端应用状态的工具,但它们的核心理念和适用场景截然不同。mobx 基于响应式原理,允许直接修改状态,代码简洁且易于上手。redux 遵循严格的单向数据流和不可变原则,强调可预测性,适合大型团队协作。vuex 是 Vue 的官方状态管理方案,深度集成于 Vue 生态,但目前已进入维护模式,官方推荐新项目使用 Pinia。
mobx、redux 和 vuex 都旨在解决前端应用中状态共享和同步的难题,但它们的实现哲学差异巨大。mobx 追求极简和响应式自动化,redux 追求可预测性和严格规范,而 vuex 则是 Vue 生态的专属方案。让我们从架构师的角度深入对比它们的实际表现。
mobx 基于 observable 模式,使用 JavaScript Proxy 自动追踪状态变化。
// mobx: 定义可观察状态
class Store {
count = 0;
constructor() {
makeAutoObservable(this);
}
increment() {
this.count++; // 直接修改
}
}
redux 基于 Flux 架构,状态是只读的,必须通过 dispatch action 来更新。
// redux: 定义 reducer
function counterReducer(state = { count: 0 }, action) {
if (action.type === 'INCREMENT') {
return { count: state.count + 1 }; // 返回新对象
}
return state;
}
vuex 也是基于 Flux 模式,但专为 Vue 设计。
commit mutation。// vuex: 定义 store
const store = createStore({
state: () => ({ count: 0 }),
mutations: {
increment(state) {
state.count++; // 必须通过 mutation
}
}
});
mobx 允许在动作中直接修改状态,逻辑最直观。
// mobx: 动作更新
class Store {
count = 0;
constructor() { makeAutoObservable(this); }
increment() {
this.count++;
}
}
redux 需要 dispatch 一个 action 对象,流程较繁琐。
// redux: 分发 action
store.dispatch({ type: 'INCREMENT' });
// 或使用 thunk
store.dispatch(async (dispatch) => {
await api.fetch();
dispatch({ type: 'INCREMENT' });
});
vuex 需要 commit 一个 mutation 字符串。
this.$store.commit 调用。// vuex: 提交 mutation
store.commit('increment');
// 异步 action
store.dispatch('fetchAndIncrement');
mobx 是框架无关的,但需要绑定层 (如 mobx-react)。
// mobx: React 绑定
import { observer } from 'mobx-react-lite';
const Component = observer(({ store }) => <div>{store.count}</div>);
redux 最初为 React 设计,但核心库是框架无关的。
react-redux 提供的 Provider 和 connect/hooks。// redux: React 绑定
import { useSelector } from 'react-redux';
const Component = () => {
const count = useSelector(state => state.count);
return <div>{count}</div>;
};
vuex 强耦合于 Vue,无法在其他框架中使用。
useStore 或 this.$store 访问。// vuex: Vue 绑定
import { useStore } from 'vuex';
const Component = {
setup() {
const store = useStore();
return () => <div>{store.state.count}</div>;
}
};
mobx 处于活跃维护状态,版本稳定在 v6+。
// mobx: 现代 API
makeAutoObservable(this); // v5/v6 标准写法
redux 核心库稳定,但官方推荐转向 @reduxjs/toolkit (RTK)。
redux 包不再推荐单独使用。// redux: 推荐写法 (RTK)
import { createSlice } from '@reduxjs/toolkit';
// 原生 redux 写法已逐渐被淘汰
vuex 处于维护模式,Vue 团队官方推荐 Pinia。
// vuex: 现状说明
// 官方文档建议:新项目请使用 Pinia 替代 Vuex
尽管实现不同,这三个库都致力于解决相同的问题。
// 共同点:集中式 store
// mobx: const store = new Store();
// redux: const store = createStore(reducer);
// vuex: const store = createStore({ ... });
// 共同点:DevTools 集成
// 均提供 chrome 扩展用于调试状态变化
// 共同点:模块拆分
// mobx: 多个 observable 类
// redux: combineReducers
// vuex: modules 选项
| 特性 | mobx | redux | vuex |
|---|---|---|---|
| 核心理念 | 响应式 Observable | 不可变状态 + Action | Flux 模式 + Vue 集成 |
| 代码复杂度 | 低 (样板少) | 高 (样板多) | 中 (结构清晰) |
| 学习曲线 | 平缓 | 陡峭 | 中等 (限 Vue 开发者) |
| 框架依赖 | 无 (需绑定层) | 无 (需绑定层) | 强依赖 Vue |
| 维护状态 | ✅ 活跃 | ✅ 稳定 (推荐 RTK) | ⚠️ 维护模式 (推荐 Pinia) |
| TypeScript | 优秀 | 优秀 (RTK) | 良好 (Pinia 更好) |
mobx 像是智能自动化系统 🤖——适合追求开发效率、喜欢面向对象风格、或需要在多框架间复用逻辑的团队。它在处理复杂依赖关系时表现卓越。
redux 像是严格的审计系统 📋——适合大型企业级应用,尤其是需要严格状态追踪、回滚功能或团队人数众多需要强约束的场景。记得使用 Redux Toolkit。
vuex 像是 Vue 的专用配件 🔌——仅建议在维护旧版 Vue 项目时使用。如果是新的 Vue 3 项目,请毫不犹豫选择 Pinia,它是 Vuex 的精神继承者,更轻更快。
最终建议:状态管理没有银弹。小型项目可能根本不需要它们(使用 React Context 或 Vue Reactivity 即可)。大型项目请根据团队技术栈和规范偏好选择:重规范选 Redux,重效率选 MobX,Vue 生态选 Pinia。
选择 mobx 如果你希望减少样板代码,偏好面向对象的编程风格,或者需要在 React 和 Vue 之间共享状态逻辑。它适合中大型项目,尤其是那些状态依赖关系复杂、需要自动追踪依赖的场景。
选择 redux 如果你需要严格的状态变更追踪、时间旅行调试,或者团队规模较大需要统一的架构规范。注意:现代 Redux 开发应优先使用 @reduxjs/toolkit 而非原生 redux 包。
选择 vuex 仅当你维护基于 Vue 2 或早期 Vue 3 的遗留项目。对于新的 Vue 3 项目,官方强烈推荐迁移至 Pinia,因为它提供了更好的 TypeScript 支持和更简洁的 API。
Simple, scalable state management.
Documentation can be found at mobx.js.org.
MobX is made possible by the generosity of the sponsors below, and many other individual backers. Sponsoring directly impacts the longevity of this project.
🥇🥇 Platinum sponsors ($5000+ total contribution): 🥇🥇
🥇 Gold sponsors ($2500+ total contribution):
🥈 Silver sponsors ($500+ total contributions):
Anything that can be derived from the application state, should be. Automatically.
MobX is a signal based, battle-tested library that makes state management simple and scalable by transparently applying functional reactive programming. The philosophy behind MobX is simple:
Write minimalistic, boilerplate-free code that captures your intent. Trying to update a record field? Simply use a normal JavaScript assignment — the reactivity system will detect all your changes and propagate them out to where they are being used. No special tools are required when updating data in an asynchronous process.
All changes to and uses of your data are tracked at runtime, building a dependency tree that captures all relations between state and output. This guarantees that computations that depend on your state, like React components, run only when strictly needed. There is no need to manually optimize components with error-prone and sub-optimal techniques like memoization and selectors.
MobX is unopinionated and allows you to manage your application state outside of any UI framework. This makes your code decoupled, portable, and above all, easily testable.
So what does code that uses MobX look like?
import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react-lite"
// Model the application state.
const myTimer = makeAutoObservable({
secondsPassed: 0,
increase() {
this.secondsPassed += 1
},
reset() {
this.secondsPassed = 0
}
})
// Build a "user interface" that uses the observable state.
const TimerView = observer(({ timer }) => (
<button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
))
ReactDOM.render(<TimerView timer={myTimer} />, document.body)
// Update the 'Seconds passed: X' text every second.
setInterval(() => {
myTimer.increase()
}, 1000)
The observer wrapper around the TimerView React component will automatically detect that rendering
depends on the timer.secondsPassed observable, even though this relationship is not explicitly defined. The reactivity system will take care of re-rendering the component when precisely that field is updated in the future.
Every event (onClick / setInterval) invokes an action (myTimer.increase / myTimer.reset) that updates observable state (myTimer.secondsPassed).
Changes in the observable state are propagated precisely to all computations and side effects (TimerView) that depend on the changes being made.
This conceptual picture can be applied to the above example, or any other application using MobX.
To learn about the core concepts of MobX using a larger example, check out The gist of MobX page, or take the 10 minute interactive introduction to MobX and React. The philosophy and benefits of the mental model provided by MobX are also described in great detail in the blog posts UI as an afterthought and How to decouple state and UI (a.k.a. you don’t need componentWillMount).
The MobX Quick Start Guide ($24.99) by Pavan Podila and Michel Weststrate is available as an ebook, paperback, and on the O'Reilly platform (see preview).
MobX is inspired by reactive programming principles, which are for example used in spreadsheets. It is inspired by model–view–viewmodel frameworks like MeteorJS's Tracker, Knockout and Vue.js, but MobX brings transparent functional reactive programming (TFRP, a concept which is further explained in the MobX book) to the next level and provides a standalone implementation. It implements TFRP in a glitch-free, synchronous, predictable and efficient manner.
A ton of credit goes to Mendix, for providing the flexibility and support to maintain MobX and the chance to prove the philosophy of MobX in a real, complex, performance critical applications.