Mobx与Redux的异同
Mobx与Redux的异同
Mobx与Redux都是用来管理JavaScript应用的状态的解决方案,用以提供在某个地方保存状态、修改状态和更新状态,使我们的应用在状态与组件上解耦,我们可以从一个地方获得状态,在另一个地方修改,在其他地方得到他们更新后的状态。他们都遵循单一数据源的原则,这让我们更容易推断状态的值和状态的修改。当然他们并不一定要跟React绑定在一起,它们也可以在AngularJs和VueJs这些框架库里使用。
描述
Redux作者说过,如果你不知道是否需要Redux,那就是不需要。在判断是否需要使用Mobx与Redux之前,我们首先需要知道他们究竟是要解决什么问题,以及当前是否遇到了这个问题。如今前端通常是要用组件components来构建一个应用,而组件中通常有自己的内部状态即state,但是随着应用越来越膨胀,组件自己内部维护的状态在膨胀的应用中很快会变得混乱。随着应用功能的不断拓展,通常会出现一些问题:
- 一个组件通常需要和另一个组件共享状态。
- 一个组件需要改变另一个组件的状态。
- 组件层级太深,需要共享状态时状态要层层传递。
- 子组件更新一个状态,可能有多个父组件,兄弟组件共用,实现困难。
这种情况下继续使用提取状态到父组件的方法你会发现很复杂,而且随着组件增多,嵌套层级加深,这个复杂度也越来越高。因为关联的状态多,传递复杂,很容易出现像某个组件莫名其妙的更新或者不更新的情况,异常排查也会困难重重。也就是说当应用膨胀到一定程度时,推算应用的状态将会变得越来越困难,此时整个应用就会变成一个有很多状态对象并且在组件层级上互相修改状态的混乱应用。在很多情况下,状态对象和状态的修改并没有必要绑定在一些组件上,我们可以尝试将其提升,通过组件树来得到与修改状态。
目前通常的解决方案是引入状态管理库,比如Mobx或Redux,Mobx与Redux都是用来管理JavaScript应用的状态的解决方案,用以提供在某个地方保存状态、修改状态和更新状态,使我们的应用在状态与组件上解耦,我们可以从一个地方获得状态,在另一个地方修改,在其他地方得到他们更新后的状态。他们都遵循单一数据源的原则,这让我们更容易推断状态的值和状态的修改。当然他们并不一定要跟React绑定在一起,它们也可以在AngularJs和VueJs这些框架库里使用。
像Redux和Mobx这类状态管理库一般都有附带的工具,例如在React中使用的有react-redux和mobx-react,他们使你的组件能够获得状态,一般情况下,这些组件被叫做容器组件container components,或者说的更加确切的话,就是连接组件connected components。通常只要将组件作为连接组件,就可以在组件层级的任何地方得到和更改状态。
对于Mobx与Redux的异同这个问题,是我最近在找实习的时候遇到的,分别为react mobx与react redux作简单的示例,文中的示例代码都在https://codesandbox.io/s/react-ts-template-forked-88t6in中。
Mobx
MobX是一个经过战火洗礼的库,他通过透明的函数响应式编程transparently applying functional reactive programming - TFRP使得状态管理变得简单和可扩展。MobX背后的哲学很简单: 任何源自应用状态的东西都应该自动地获得,其中包括UI、数据序列化等等,核心重点就是: MobX通过响应式编程实现简单高效,可扩展的状态管理。
// src/mobx-store/store.ts
import { observable, action, makeAutoObservable } from "mobx";
class Store {
constructor() {
makeAutoObservable(this);
}
@observable
state = {
count: 1
};
@action
setCount = (value: number) => {
this.state.count = value;
};
@action
setCountIncrement = () => {
this.state.count++;
};
}
export default new Store();
// src/counter-mobx.tsx
import React from "react";
import { observer } from "mobx-react";
import store from "./mobx-store/store";
const CountMobx: React.FC = () => {
return (
<div>
<div>{store.state.count}</div>
<button onClick={() => store.setCount(1)}>Set Count value 1</button>
<button onClick={store.setCountIncrement}>Set Count Increment</button>
</div>
);
};
export default observer(CountMobx);
Redux
Redux用一个单独的常量状态树或者叫作对象保存这一整个应用的状态,这个对象不能直接被改变,当一些数据变化了,一个新的对象就会被创建,严格的单向数据流是Redux架构的设计核心。
// src/redux-store/store.ts
import { createStore } from "redux";
const defaultState: State = {
count: 1
};
export const actions = {
SET_COUNT: "SET_COUNT" as const,
SET_COUNT_INCREMENT: "SET_COUNT_INCREMENT" as const
};
const reducer = (state: State = defaultState, action: Actions): State => {
const { type } = action;
switch (type) {
case actions.SET_COUNT: {
return { ...state, count: action.payload };
}
case actions.SET_COUNT_INCREMENT: {
return { ...state, count: state.count + 1 };
}
default:
return state;
}
};
export const store = createStore(reducer, defaultState);
export interface State {
count: number;
}
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
type SET_COUNT_INCREMENT = {
type: typeof actions.SET_COUNT_INCREMENT;
payload: void;
};
type SET_COUNT = {
type: typeof actions.SET_COUNT;
payload: number;
};
export type Actions = SET_COUNT_INCREMENT | SET_COUNT;
// src/counter-redux.tsx
import React from "react";
import { AppDispatch, actions, State } from "./redux-store/store";
import { useSelector, useDispatch } from "react-redux";
const CountRedux: React.FC = () => {
const count = useSelector((state: State) => state.count);
const dispatch = useDispatch() as AppDispatch;
return (
<div>
<div>{count}</div>
<button onClick={() => dispatch({ type: actions.SET_COUNT, payload: 1 })}>
Set Count value 1
</button>
<button
onClick={() =>
dispatch({ type: actions.SET_COUNT_INCREMENT, payload: void 0 })
}
>
Set Count Increment
</button>
</div>
);
};
export default CountRedux;
// src/App.tsx
import React from "react";
import "./styles.css";
import CountMobx from "./counter-mobx";
import CountRedux from "./counter-redux";
import { Provider as ReduxProvider } from "react-redux";
import { store } from "./redux-store/store";
const App: React.FC = () => {
return (
<div>
<div>======Mobx======</div>
<CountMobx />
<br />
<div>======Redux======</div>
<ReduxProvider store={store}>
<CountRedux />
</ReduxProvider>
</div>
);
};
export default App;
相同点
- 为了解决状态管理混乱,无法有效的同步的问题,统一管理应用状态。
- 一个状态只有一个可信的数据源,通常是以
action的方式提供更新状态的途径。 - 都带有状态与组件的链接管理库,例如
react-redux、mobx-react。
不同点
函数式和面向对象
Redux更多的是遵循函数式编程Functional Programming, FP思想,从数据上来说Redux理想的是immutable,immutable对象是不可直接赋值的对象,它可以有效的避免错误赋值的问题,例如reducer就是一个纯函数,对于相同的输入总是输出相同的结果。Mobx则更多从面相对象Object Oriented Programming, OOP与响应式编程Reactive Programming角度考虑问题,从数据上说Mobx从始至终都是一份引用,这样可以使的Mobx的组件可以做到精准更新,将状态包装成可观察对象,一旦状态对象变更,就能自动获得更新。
store管理方式
- 在
Redux应用中通常将整个应用的state被储存在一棵object tree中,并且这个object tree只存在于唯一一个store中。 - 在
Mobx则通常按模块将应用状态划分,在多个独立的store中管理。
储存数据形式
Redux默认以JavaScript原生对象形式存储数据,这也就使得Redux需要手动追踪所有状态对象的变更。- 在
Mobx使用可观察对象,通常是使用observable让数据的变化可以被观察,通过把属性转化成getter/setter来实现,当数据变更时将自动触发监听响应。
不可变和可变
Redux状态对象通常是不可变的Immutable,复制代码我们不能直接操作状态对象,而总是在原来状态对象基础上返回一个新的状态对象。Mobx状态对象通常是可变的Mutable,可以直接使用新值更新状态对象。
状态调试
Redux提供进行时间回溯的开发工具,同时纯函数以及更少的抽象,让调试变得更加容易。Mobx中有更多的抽象和封装,调试会相对比较困难,同时结果也相对难以预测。
最后
Mobx与Redux都是非常棒的两个库,使用上没有对错,只有合适不合适,只是可能需要在使用之前做好调研工作。或许有人需要减少编写的代码行数,那么就可能会提到Redux有太多的样板代码,而应该使用Mobx,可以减少xxx行代码。又或许有人需要更加明确的处理对象的变更,那么就可能感觉放弃Mobx的响应式魔法,而使用Redux去通过纯 JavaScript来推断与调试。又或许两个状态管理库并不冲突,可以同时存在,分别管理不同的模块的状态。
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://cn.mobx.js.org/
https://www.redux.org.cn/docs/react-redux/
https://juejin.cn/post/6844903977553756168
https://juejin.cn/post/6924572729886638088
https://segmentfault.com/a/1190000011148981
https://www.cnblogs.com/tommymarc/p/15768138.html
https://blog.csdn.net/leelxp/article/details/108450518
https://blog.csdn.net/Ed7zgeE9X/article/details/121896197
https://yangleiup.github.io/accumulate/redux%E4%B8%8Emobx%E5%8C%BA%E5%88%AB.html
https://medium.com/@pie6k/better-way-to-create-type-safe-redux-actions-and-reducers-with-typescript-45386808c103
Mobx与Redux的异同的更多相关文章
- 你需要Mobx还是Redux?
在过去一年,越来越多的项目继续或者开始使用React和Redux开发,这是目前前端业内很普遍的一种前端项目解决方案,但是随着开发项目越来越多,越来越多样化时,个人又有了不同的感受和想法.是不是因为已经 ...
- Mobx与Redux区别
Mobx的实现思想和Vue几乎一样,所以其优点跟Vue也差不多:通过监听数据(对象.数组)的属性变化,可以通过直接在数据上更改就能触发UI的渲染,从而做到MVVM.响应式.上手成本低.开发效率高,在数 ...
- Mobx总结以及mobx和redux区别
Mobx解决的问题 传统react使用的数据管理库为Redux.Redux要解决的问题是统一数据流,数据流完全可控并可追踪.要实现该目标,便需要进行相关的约束 Redux由此引出dispatch ac ...
- 几个月来使用mobx代替redux的一些总结
遇到的一些小坑 React组件内部想要调用store里的action方法,得如下图,否则不会调用(这个现在看来好像不对,待重新检验) 而不能如下图 组件中调用改变store的action后,状态变化并 ...
- redux、immutablejs和mobx性能对比(三)
四.我的结论 通过第三部分的数据数据分析,我觉得我们可以得到以下结论: 无论是在开发环境还是测试环下页面的首次加载速度结果都是:redux>immutablejs>mobx,但是他们之间的 ...
- 在react项目中使用redux or mobx?
主要比较参数: 库体积,打包项目体积 开发体验 性能对比 在对比参数前首先分析一下redux和mobx的设计模式,redux和mobx都没有使用传统的mvc/mvvm形式,而且他们使用flux结构也略 ...
- 【译】Redux 还是 Mobx,让我来解决你的困惑!
原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用了 Redux,但我最近都在使用 Mob ...
- Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案
近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...
- 十分钟介绍mobx与react
原文地址:https://mobxjs.github.io/mobx/getting-started.html 写在前面:本人英语水平有限,主要是写给自己看的,若有哪位同学看到了有问题的地方,请为我指 ...
- mobx源码解读1
mobx是redux的代替品,其本身就是一个很好的MVVM框架.因此花点力气研究一下它. 网上下最新的2.75 function Todo() { this.id = Math.random() mo ...
随机推荐
- [转帖]Nginx内置变量以及日志格式变量参数详解
https://www.cnblogs.com/wajika/p/6426270.html $args #请求中的参数值 $query_string #同 $args $arg_NAME #GET请求 ...
- [转帖]strace分析sqlplus登录慢问题
一. 问题分析 有时会遇到sqlplus / as sysdba登录非常慢的问题,由于还没登录,通过数据库等待事件一般看不出来啥,需要用到strace这个分析利器.strace有很多参数,后面会列出, ...
- [转帖] 请求量突增一下,系统有效QPS为何下降很多?
https://www.cnblogs.com/codelogs/p/17056485.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 最近我观察到一 ...
- [转帖]浅谈redis采用不同内存分配器tcmalloc和jemalloc
http://www.kaotop.com/it/173669.html 我们知道Redis并没有自己实现内存池,没有在标准的系统内存分配器上再加上自己的东西.所以系统内存分配器的性能及碎片率会对Re ...
- [转帖]awk命令 去掉重复行
https://developer.aliyun.com/article/885946?spm=a2c6h.24874632.expert-profile.263.7c46cfe9h5DxWK lin ...
- [转帖]【JVM】堆内存与栈内存详解
堆和栈的定义 java把内存分成栈内存和堆内存. (1)栈内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配. 当在一段代码块中定义一个变量时,java就在栈中为这个变量分 ...
- [专题]中立遭质疑,提价遭反对,ARM的生存难题怎么破?
中立遭质疑,提价遭反对,ARM的生存难题怎么破? https://news.cnblogs.com/n/669715/ ARM税要提高.. RISC-V的机会? 文/黎文婕 来源:锌刻度(ID:znk ...
- 使用Grafana 监控 SQLSERVER数据库
使用Grafana 监控 SQLSERVER数据库 1.获取镜像信息以及启动镜像 docker pull awaragi/prometheus-mssql-exporter docker run -e ...
- 我在京东做研发 | 京东云算法科学家解析爆火的ChatGPT
令人惊艳的ChatGPT横空出世 背后有怎样的前沿技术支撑 走向大规模产品应用又有何局限 深耕对话式AI技术十余年 京东云算法科学家将带您一同走进技术世界 解析ChatGPT的技术亮点与局限 分享下一 ...
- elementui更改Slider 滑块颜色样式
<div class="con-slider"> <el-slider :disabled="disabledFlag" @change=&q ...