sorrycc / blog

💡
4.48k stars 325 forks source link

MobX 和 Redux 的比较 #5

Open sorrycc opened 8 years ago

sorrycc commented 8 years ago

先要明白 mobx 和 redux 的定位是不同的。redux 管理的是 (STORE -> VIEW -> ACTION) 的整个闭环,而 mobx 只关心 STORE -> VIEW 的部分。

但作为两个目前最火的 React 应用框架库,人们习惯于把他们比较到一起。下面我们也来看下 mobx 和 redux 相比的优缺点。(据说每个列 3 点会让人更容易记住。。)

优点

基于运行时的数据订阅

mobx 的数据依赖始终保持了最小,而且还是基于运行时。而如果用 redux,可能一不小心就多订阅或者少订阅了数据。所以为了达到高性能,我们需要借助 PureRenderMixin 以及 reselect 对 selector 做缓存。所以,如果。

OverSubscription 的例子:

  1. 非实时计算
view() {
  if (count === 0) {
    return a;
  } else {
    return b;
  }
}

基于 redux 的方案,我们必须同时监听 count, a 和 b 。在 counte === 0 的时候,b 如果修改了,也会触发 view 。而这个时候的 b 其实是无意义的。

  1. 粗粒度 subscription
view() {
  todos[0].title
}

基于 redux,我们通常会订阅 todos,这样 todos 的新增、删除都会触发 view 。其实这里真正需要监听的是 todos 第一个元素的 title 属性是否有修改。

通过 OOP 的方式组织领域模型 (domain model)

OOP 的方式在某些场景下会比较方便,尤其是容易抽取 domain model 的时候。进而由于 mobx 支持引用的方式引用数据,所以可以非常容易得形成模型图 (model graph ),这样可以更好地理解我们的应用。

修改数据方便自然

mobx 是基于原生的 JavaScript 对象、数组和 Class 实现的。所以修改数据不需要额外语法成本,也不需要始终返回一个新的数据,而是直接操作数据。

缺点

缺最佳实践和社区

mobx 比较新,遇到的问题可能社区都没有遇到过。并且,mobx 并没有很好的扩展/插件机制。

随意修改 store

我们都知道 redux 里唯一可以改数据的地方是 reducer,这样可以保证应用的安全稳定;而 mobx 可以随意修改数据,触发更新,给人一种不安全的感觉。

最新的 mobx 2.2 加入了 action 的支持。并且在开启 strict mode 之后,就只有 action 可以对数据进行修改,限制数据的修改入口。可以解决这个问题。

逻辑层的限制

如果更新逻辑不能很好地封装在 domain class 里,用 redux 会更合适。另外,mobx 缺类 redux-saga 的库,业务逻辑的整合不知道放哪合适。

jzlxiaohei commented 8 years ago

如果更新逻辑不能很好地封装在 domain class 里 这里的更新逻辑具体是指什么

我这边用mobx做了个小项目,目前没发现不能cover的逻辑。

JimmyLv commented 8 years ago

@jzlxiaohei 能分享一下项目 GitHub 吗?

luobotang commented 7 years ago

感觉 MobX 很有些 MVVM 的味道啊

lefter commented 7 years ago

@sorrycc 我们正在做一个富应用(类似百度H5的网页编辑器),包括你的DVA,哪个更合适一点?

tangkunyin commented 7 years ago

看来目前还是用Redux妥当啊

xiangst0816 commented 7 years ago

@JanzenZhangChen 这里: Mobx和VUE都太自由了,随意修改store就造成更新,必然导致bug极难定位你这个论断是怎么得出的, 能具体说说嘛?

JanzenZhangChen commented 7 years ago

@xiangsongtao 我的描述确实有点问题,不是因为随意修改store,就会导致bug。而是会导致逻辑的封装不严谨。对store的不同操作逻辑可能被放在各个不同的组件内,不能被抽象出来,导致这个组件很可能没办法很好的复用,或是解耦。在多人团队合作的时候,很可能因为高自由度而导致逻辑的混乱。

目前用Mobx和vue开发小项目都很爽。但是在SPA项目中使用确实没有redux来的有安全感。感觉C层会越写越薄,View会承载大量逻辑。最后就导致维护的难度上升。

xiangst0816 commented 7 years ago

@JanzenZhangChen 我使用mobx的时间不多, 我觉得每个路由应该对应一个特定的页面(比如dashboard和email两个不同的页面), 而这个页面的状态store应该由这个页面自己管理, 而不是在全局管理. 如果需要用到公共状态, 比如theme, 则通过inject注入到需要的页面中. 整个过程还算可控.

也许做过大项目才能体会到你说的'安全感', 谢了

doodlewind commented 7 years ago

@JanzenZhangChen 使用 mobx 符合领域模型的 class 在中小项目中能提高效率,并不意味着大项目中就不适合吧。Java 大项目照样用 OO 的这一套抽象啊。个人理解,二者实际上区别应该在于 Redux 适合 IM 一类状态随时间序列变化的系统,而 mobx 更适合后台管理等对许多复杂数据模型做 CRUD,没有时间序列概念的系统。

JanzenZhangChen commented 7 years ago

@xiangsongtao @doodlewind 我个人感觉,其实这个问题不是简单的对错,而更多是一个权衡。 更多的是架构设计的方式不同。 store被reducer管理之下,其实还是很清晰的。 我觉得和OO的这一套最大的本质差别在于,对数据的操作逻辑放在哪里?(这句话其实也有问题,最大的区别应该是命令式编程与函数式编程的区别

redux控制下MVC的分层会很明显,view会很纯粹。但是逻辑就被分散到C层,M层(reducer)。虽然写起来很烦,但是分层以后,相对降低了维护的难度。我认为这是SPA最需要解决的痛点。复用的其实就只有view层,对数据的处理逻辑就要另外用。

mobx(vue)控制下因为没有action,reducer的承载,对model的操作会倾向写在view里面,使其变得大且复杂。当逻辑多了以后,这个组件就需要承载组件通信,复杂业务逻辑,还有一些对dom的特殊处理等问题。这些都会在一个组件内完成。那么维护这些逻辑的成本就会随着迭代急剧上升。也因为逻辑都在一个地方,所以直接使用一个复杂业务逻辑组件就简单很多。如果这时候来一个特殊需求,你就只能在这个组件内写特殊逻辑分支了。在redux内则不会有这个问题。

jzlxiaohei commented 7 years ago

mobx 有action的感念。 strict模式下,必须标记了@action才能修改对象。 当然view里也能标记,所以我们要求 view里必须使用model 自己的方法修改数据。

我们的代码了,组件一般需要一个model,例如

static propTypes = {
  model: PropTypes.instanceOf(UserModel).isRequired,
}

作为深受OO‘毒害的人’, 这种是我接受起来就容易的方式了,组件需要什么model, model里有组件需要的数据(字段)和action(方法)。业务模型一目了然,反而是redux的业务模型,散落在action和reducer里,让我觉得表述业务时,有点不清楚。

doodlewind commented 7 years ago

mobx(vue)控制下因为没有action,reducer的承载,对model的操作会倾向写在view里面

我很赞成 @JanzenZhangChen 纯 View 的理念,不过你提到的这点不完全成立。mobx 有 strict 模式来强制把 model 操作封装在 action 中,也同样也可以围绕 model 和 store 来组织代码,让 View 保持为 React 应该有的纯 View。这样不仅保留了和 Redux 理念上一致的模型层抽象,也能够提升开发的效率,少写 redux 的 boilerplate(我们组内交流的观点还是普遍反映 redux 这一套比较难用,目前在考量 Rx+mobx 的方案)。

jzlxiaohei commented 7 years ago

@doodlewind 我用下来,mobx不太需要和rx配合,直接数据驱动就好,流式的,毕竟很少真正需要。

另外mobx的作者,又写了个 mobx-state-tree, 我感觉这个几乎把redux一些理念上优点都集成进来了,不过有点复杂,而且比较新(意味着可能有坑

JanzenZhangChen commented 7 years ago

@jzlxiaohei @doodlewind 嗯,我后面没怎么跟进mobx的演化了。其实我也挺喜欢mobx的,只是现在还不敢贸然在正式环境上线。

jzlxiaohei commented 7 years ago

我基本都是后台项目。 mobx + antd 加了polyfill, IE9可以用。 (firefox好像反而没人问

sxlvalue commented 6 years ago

感觉MBOX灵活,MVVM的,数据驱动,理解特别容易,VIEW只是STATE的一个展现。

mqliutie commented 5 years ago

没用过mobx 不知道是否有和vuex一样监测store的变化 否则组件内部直接修改store确实比较难维护

image