ReactJS 还在纠结 Flux 或 Relay,或许 Redux 更适合你

camel · 发布于 2015年08月16日 · 最后由 luikore 回复于 2015年08月17日 · 24179 次阅读
558
本帖已被设为精华帖!

重磅消息,Redux 1.0 发布,中文文档同步上线,终于可以放心用于生产环境了!

Redux 1.0 Cheers

在这个端应用技术膨胀的时代,每天都有一大堆框架冒出,号称解决了 XYZ 等一系列牛 X 的问题,然后过一段时间就不被提起了。但开发的应用还是需要维护的!所以选择框架时不要只顾着自己用着爽,还要想着以后别人接手时的难易度。

因为 Flux 本身约定不够细致,如何做异步、如何做同构这些非常普遍的问题,官方都没有给出详细的说明。还有 store,view 里一大堆重复代码,极速膨胀的 action 等问题。这也难免会冒出一堆“改良”性的轮子。有一些非常闪光,如 Redux,Reflux,Marty。Reflux 和 Marty 基本上只是去掉重复代码并为现有 Store,Action 增加一些灵活性,用起来比原生 Flux 上手更容易,但是总体二者没有跳出 Flux 的思想,大量依旧采用“传统”的 mixin 方式实现。如果项目不是很复杂可以试试。至于 Relay,由于需要后端 GraphQL 支持,对于采用 REST 接口开发的遗留项目和前后端分离的大团队来说成本切换有点高。

现在开始说今天的主角 Redux。Redux 由 Flux 演变而来,后来受 Elm 启发,去掉了 Flux 的复杂性,到现在越来越自成一派,甚至已经有了 Angular 的实现。最近开始把团队旧的纯 Flux 开发项目逐步往 Redux 上迁移。Redux 还是秉承了 Flux 单向数据流Store is the single source of truth 的思想,这两点略过。下面谈一下使用 Redux 过程中的其它感受。

特性和优点

文档清晰,编码统一

Redux 文档非常清晰细致,这一点有助于统一团队编码风格,节省了很多纠结和踩坑的时间。再也不纠结 Ajax 请求到底放哪里了,全部丢到 action(通用的也可以放到 middleware) 里就没错。究竟使用 state 还是 props?组件里全部使用 props,只在顶层组件里使用 state。之前为了灵活或兼容性,Redux 的 provider 提供 Provider decorator 装饰器 和 provider 两种调用用法,现在只建议使用 Provider decorator。Redux 这点设计思想和 Python 的非常像:

There should be one, and preferably only one - obvious way to do it.

你会发现用了 Redux 后,整个团队写的代码风格都比较一致,上一次有这种感受是项目由旧的 jQuery 组件迁到 React 的时候。如果有些场景你还是纠结怎么办?去 Redux issues 提个 issue 吧,很快就会有人回复。

State, State, State -> Store

前端复杂性在于 view,view 复杂性在于 state 处理。state 复杂是因为包括了 AJAX 返回的数据、当前显示的是哪个 tab 等这些 UI state、表单状态、甚至还有当前的 url 等。Redux 把这些所有的 state 汇总成一个大的对象,起了个名字叫 Store,没错,就是 Flux 里的 Store。只是 Redux 限定一个应用只能有一个 Store。单一 Store 带来的好处是,所有数据结果集中化,操作时的便利,只要把它传给最外层组件,那么内层组件就不需要维持 state,全部经父级由 props 往下传即可。子组件变得异常简单。

Reducer

只有一个 Store,第一感觉是这个 Store 对象会不会非常大?其实对象大并不可怕,可怕的是对象处理逻辑放到一起。只要把这些处理逻辑按处理内容拆分不就可以了吗?!拆分后的每块处理逻辑就是一个 Reducer。把这些 Reducer 里的每块内容合到一起(用 ES6 的 import 语法)就组成了完整的 StoreReducer 只是一个纯函数,所以很容易测试。提到 Reducer 不得不提函数式编程,reducer 本质就是做对象格式转换,这点用函数式操作实在太高效了。

(previousState, action) => newState

因为是纯函数,组合多个 reducer 非常简单,参见 https://gist.github.com/gaearon/d77ca812015c0356654f。顺便也移除了 Flux 里最让人诟病的 waitFor 语法。

Action

Redux 的 action 与 Flux 中的类似,都是表达 view 要改变 store 内容的载体。Flux 是通过统一的 Dispatcher 分发 action,Redux 去除了这个 Dispatcher,使用 store 的 store.dispatch() 方法来把 action 传给 store。由于所有的 action 处理都会经过这个 store.dispatch() 方法,Redux 聪明地利用这一点,实现了与 Koa,Ruby Rack 类似的 Middleware 机制。Middleware 可以让你在 dispatch action 后,到达 store 前这一段拦截并插入代码,可以任意操作 action 和 store。很容易实现灵活的日志打印、错误收集、API 请求、路由等操作。我们团队根据预建立的 action 和请求间的映射直接在这里直接发 Ajax 请求,从此麻麻再也不用担心我异步取数据了。

除了这些之外,还有逆天的 DevTools,可以让应用像录像机一样反复录制和重放。

Redux DevTools

对于同构应用 Redux 也有很好的支持,这一块团队正在调研,等实际上线后再做分享。

不足或不便

当然使用过程中也有一些不顺利的地方,其实主要还是思想方面的转变。

组件应尽可能无状态化

这也被称为 Smart Component 和 Dumb Component 之间的选择,组件库开发应尽可能做成 Dumb Component。这一点和传统的 jQuery 类普遍使用命令式语法做组件开发有很大不同。如写一个 Dialog,jQuery 组件一般会提供 dialog.show(), dialog.hide() 方法。但 Redux 要求显示或隐藏应该被当作一个 props,由外部传入来控制。Redux 比 Flux 更严格要求 Store 作为数据来源的惟一性,所以之前能用的组件现在发现直接不能用了。

轮训和 WebSocket 请求的处理

请求的发起要在 action 里做,但是请求的暂停/启动状态要放到 store 里,会增加一些复杂性,但保证了数据的一致性。其实还是未明确 store 是单一数据源的思想。

资料:

官方地址:https://github.com/rackt/redux 中文文档:http://github.com/camsong/redux-in-chinese 项目列表:https://github.com/xgrommx/awesome-redux 同构示例:http://react-redux.herokuapp.com/ Rails 示例:https://github.com/alexfedoseev/generator-flux-on-rails

对了,听说中文文档翻译的还不错,连 Redux 作者 Dan Abramov 都推了,要不你也看看 :D

image


原文地址:https://github.com/camsong/blog/issues/1

近期会整理更多 React,Redux 相关开发实践,请关注我的博客

共收到 56 条回复
16228

才刚开始学ember,感觉真是跟不上前端的脚步了

3

如果有人想挖 @camel 的话,可以联系我,我是 @camel 的经纪人 😏

775

还不如直接用Elm

558

@lgn21st 开始歪楼了,老板该发工资啦 💰

搭车招前端,阿里巴巴急招前端工程师,简历快扔过来吧

Eda824

#1楼 @chaucerling 单向流,action改变状态这些都是对的,但是没有模板,在jsx里面直接写HTML,我总觉得哪里不对。。

15615

关注一下!

558

#5楼 @ericguo 养成习惯可以提高开发和沟通效率,但也会阻碍接受新东西。当你还在纠结 jsx 的时候,有人已经抛弃 CSS,用纯 JS 来做了。 感觉这东西在体验了之后可以改的。

239

#1楼 @chaucerling 继续学ember吧。因为ember有其他框架没有的特征。个人觉得emberjs的软件工程做的非常不错。

239

#5楼 @ericguo 说得非常对。一般公司都是会有前后端工程师以及设计师,react有种把那些html css的活跟js粘合起来不可分割的感觉。这样我们团队那个只懂html css的前端设计师就没办法发挥他的作用了。这点angularjs2.0的做法比较不错。

个人非常讨厌那种类库快速升级而不顾虑老用户的开源软件和作者。emberjs的这点做的非常好,在2.0的之前,已经一步一步让用户给升级了,每一升级都是一点一点来的。痛苦不是积聚起来的。这种开源团队和思想我觉得值得信赖多一点

27

现在的开发者都是喜欢跟风,React 的是 virtual dom 思想确实牛逼,不过现在带 virtual dom 的框架多得是,而且好多都比他性能好,写法也没那么蛋疼,不知道为什么非要盯着 React 不放

2880

培根饿了么解决你的烦恼

239

#11楼 @luikore 我觉得,一旦要想轻量级的解决方案,就有一堆选择的问题。部署,编译还有其他各种必要的插件的选择。

558

本来想聊一下 react 相关经验,现在变成了与 ember 之间的选择问题,哈哈,这样也好,从当初 discourse 出来的时候就有尝试过 ember,Yehuda 也是我最佩服的开发者之一。

关于我对 @hlxwell 快速升级而不顾虑老用户的开源软件和作者 的看法。React 在这点做的不错,从去年7月份 0.8 版本一路升过来,没有踩过大坑。Redux 相信有了 1.0 版本之后,API 也会比较固定。甚至由于 react 非常专注做 view 层,整个应用架构从 backbone 迁到 flux 过程中 view 层变化也很少,最近又在从 flux 迁到 redux,react view 层也保持不变。至于迁移原因,一是因为产品用户增多,越来越复杂,二是有好东西出来,为啥不用???move fast and break things 一直是我想达到的状态。

把 react 和 ember 比不太合适,两个框架走的是两条路。ember 是一个全面的前端解决方案,而 react 只专注做 view 层。如果你不喜欢选择,直接上 ember 是可以。不过从长远来看,前端越来越复杂,完整的解决方案是不存在的,轻量级的方案会胜出。

下面说一下我理解的轻量级解决方案标准:

  • 只做一件事情,并做好。
  • 面向未来,尽可以使用标准化工具,如 CommonJS,ES6,NPM 开发构建。如果你只对解决 IE 兼容性有兴趣,而不想学习下最新的 ES6,Decorator 语法,提前告诉你,未来的前端不适合你。
  • 没有三方依赖,框架尽可能小,文档尽可能多。这是选择 Redux 的原因之一,整个框架只有 360 行左右。
2852

#10楼 @numbcoder React 相对来说上手比较容易吧,不过后期的学习曲线还是有的。

558

#3楼 @nouse Elm 是一种新的语言,虽然可以编译成 JavaScript,但在团队里推广成本大。 #11楼 @luikore bacon.js 没用过,貌似也是很棒的 FRP 框架。不过 Bacon 有 3000+ 行,Redux 大小只有它的十分之一。

另外补一句:

1、React 就是 JavaScript;Ember 是 EmberScript,Angular 是 TypeScript + AngularScript; 2、PHP 是世界上最好的语言 😄

2474

居然也有devtools。。。

2852

我感觉 javascript 的学习成本主要还是百花齐放,每家做框架的都有自己的思想,更新又快,文档又少,startup又杂,根本没有一个统一的方案。再加上各种构建工具,各种规范思想,一下AMD,一下又CommonJS。完了一个项目还没整明白,ES5、ES6又出来了,跑在线上的项目又不敢轻易升级。最蛋疼的是老板用IE,让你去找一个支持IE的方案,github上issues看了半天,最后想想,还是不用了。

15615

IE看来已经被前端大神彻底放弃了,很多前端框架都抛弃了大部分IE版本。

15615

非常认同@luikore 的看法, javascript 用了这么久,一直还无法入门。

2575

@luikore @MrPasserby 这就是 JavaScript 的世界,西部大开发…… 不过也是吸引人之处。真的哪天不折腾了,说明很多问题都有了标准化的解决方案,JavaScript 发展速度也就缓慢下来了,喜欢折腾的人也会去开拓新的蛮荒之地。

D77582

用react+flux很久了,看到redux,试试看这东西好不好用

90

#18楼 @luikore 这么评价 Flux, 看来对 Backbone 更要打压一下.

1289

决定继续用自己的屌丝架子

A87c18

组件里全部使用 props,只在顶层组件里使用 state。

这点不错。

558

@wppurking 喜欢你这种有想法又详细表达出来,有理有据,先给个赞。

大家在用不同的方法解决相同的问题,因为问题是一样的。

关于 Relay 和我的看法一样。我还觉得 Relay 有可以在获取数据上颠覆 REST。

最终总会出来非常相似的组件...

这点已经是现实了,看一下 bootstrap,在不同框架下都有单独的实现。组件虽然看起来一样,用起来也一样,但实质是不一样的。因为组件和你上面说的 Data、View、 Action 这些是很难做到完全剥离,所以再写一套大部分情况下是有必要。严重怀疑 Web Component 能否解决这个问题。

想做到不迷失我觉得要让自己足够开放,就像今天尤小右在 Teahour 里说的,不要过早宣布了自己发现了最好的框架。有精力的话多尝试不同方法,提高自己的判断能力。

#22楼 @darkbaby123

这就是 JavaScript 的世界,西部大开发……

这个比喻太恰当了。

775

#16楼 @camel 和purescript这种js界的haskell相比,elm就没有那么追求纯粹,更讲求实用

239

#27楼 @wppurking 5点核心本质分析到位。

239

#14楼 @camel move fast and break things 我觉得对developer来说没问题,但是对于公司来说,变化不是问题,而程序员好变带来的成本是个问题。

下面说一下我理解的轻量级解决方案标准:

只做一件事情,并做好。
面向未来,尽可以使用标准化工具,如 CommonJS,ES6,NPM 开发构建。如果你只对解决 IE 兼容性有兴趣,而不想学习下最新的 ES6,Decorator 语法,提前告诉你,未来的前端不适合你。
没有三方依赖,框架尽可能小,文档尽可能多。这是选择 Redux 的原因之一,整个框架只有 360 行左右。

我觉得其实Rails已经做了非常好的就是Rails放在一起时一个组合金刚,但是实质上他是可以一个一个分开工作的组建。现在ember-data是有单独的包的,如果以后, routing, component 都独立出来的话,其实这样大框架也不在笨重。放在一起也非常强大。这个是最好的状态。

还有 Dedux 的确非常简单。非常赞。

11222

能解决的问题各个框架都差不多,不能解决的脏活累活还得jQuery或者vanilla来干。

2443

#28楼 @camel 😄 赞收到 @hlxwell Dedux => Redux 😁

前端的 angular, react.js, emberjs 这三个体系为你提供的完整的前端解决方案. 这三种纯前端方案在现在的前端领域里面是佼佼者, 无论你选择哪一个你都不会被带偏. 如果实在想知道选择哪一个? 那么就自己拿支笔, 拿张纸尝试着将你感兴趣的浏览器前端框架/工具向上面那五个点所组成的圈圈里面套, 哪些能够更加适合你现在的项目你就选哪个. 如果想看工程编码方面的, 找开源项目去了解, 找符合你代码口味的. (看多了会麻木的... 所以有空写个 demo 也无妨)

附带一些成功的案例, 大家用的都很 Happy~

angularjs

react.js

ember.js

239

#33楼 @wppurking #28楼 @camel

帅哥,看你们react都用了许久,想问一下,如果想像Ember-CLI那样,把 redux, 很多东西任务都标准话的话,比如配置好的yo, gulp,有很多generator, 以及build, testing, 你们有没有推荐,我不用自己去瞎折腾,团队共识建立快的那种?

239

#33楼 @wppurking

https://ghost.org/ 开源的,也是用emberjs 然后 itune connect 后台图表的是 angularjs

2575

作为 Ember 粉,再加一个 Built With Ember

558

#34楼 @hlxwell 这个团队内部有写 CLI,不过和公司系统关联太多,不便开源。 现在最流行的工具链是 NPM + Webpack + Babel + Mocha... 这些。想写个功能强大的 CLI 有点难,对每个 Flux 衍生框架都做个 generator 会让人崩溃。有一股去 bower,grunt,gulp 的趋势。

小团队的话直接找个 boilerplates 改就行了 https://github.com/enaqx/awesome-react#boilerplates

96

#1楼 @chaucerling 前端变化太快 光构建就: grunt -> gulp -> webpack ...

871

楼主还是组织个线下活动更好

2909

#16楼 @camel 想写react,但是公司不给机会,自己之前练手过,现在全忘了。 还在弄angular。 对了,现在commonjs和es6已经是事实上的前端开发标准了吗? 我还在弄amd。是不是过时了啊?

另外一个合格的前端是不是还要会写nodejs的api?

2909

#37楼 @camel bower实在是挺蛋疼的,grunt,gulp在我看来几乎就是用于自动化发布的功能。

webpack和component没研究过(随便看了看),我也是希望能有更合适的工具,能够更加细粒度的component化组件。

558

#40楼 @1272729223 公司不给机会好办,要不你简历发过来我帮你找找。

现在commonjs和es6已经是事实上的前端开发标准了吗? 我还在弄amd。是不是过时了啊?

是的,AMD 已过时;CommonJS,es6/es7 已是标准

另外一个合格的前端是不是还要会写nodejs的api?

这个要看具体团队,js 能写好,nodejs api 也不难

ps: bower,grunt,gulp 都已过时(我就是来挨喷的) pps: 过时并不代表你不可以用,只是说如果有选择的机会,尽量不用

2909

#42楼 @camel 谢谢,我打算用commonjs和es6的规范来写两个sample先,至少先熟悉了他们的规范。 至于nodejs api那块,单纯对于expressjs这个框架而言我觉得上手应该3-5天,但是要熟悉估计得至少练习1-2个月以上。

我也老早就想去掉bower了(实在难用),grunt,gulp,是不是用webpack和component就能替代了?

558

#43楼 @1272729223 grunt, gulp 只是任务执行器,需要调用第三方工具 webpack/node-sass/component 才能编译 JS,SCSS。

会被 npm 替代,原来的 webpack/node-sass/component 该用啥继续。

Eda824

#14楼 @camel 认同你的“不过从长远来看,前端越来越复杂,完整的解决方案是不存在的,轻量级的方案会胜出。”观点,这个也是vue.js作者的观点,但是(凡事总有但是。。),我真的无法确定未来哪个轻量级方案会胜出。。

所以对自己能力没信心的我还是选择Ember.js,最有opinion的框架,等我完全掌握了以后再转也来得及吧,就像现在我从Rails转Ember.js一样。

2909

#44楼 @camel 谢谢,我回头研究下

96

一直在用 reflux,感觉很好

1141

其实很早我就发现, ruby-china里面很多讨论的东西不是ruby而是 js了.. js好热, ember 有一点不好是有点大, 做 webapp 貌似不太合适..

15615

ruby是核心,是根据地。周边是生态。要维护生态平衡,开放共赢吗!

558

#47楼 @steven_yue Reflux 特别灵活,它的 action 设计的太灵活强大了,view 里直接监听 action 这一点瞬间把 Flux 门槛拉的极低,虽然这是标准 Flux 不建议做的。如果不考虑做同构、Time Travel、Do/Undo 这些 Reflux 是不错的选择。

#48楼 @feitian124 认识几个做 rails 开发大部分时间都在调 js 😄 因为 rails 接口三下五去二就搞好了

2909

#50楼 @camel 我想问下,如果单纯用browserify(或者webpack), 能否完全去掉用(grunt|gulp)scss,image,font等其他资源的编译,复制,压缩等,以及处理发布应用的任务? 我研究了几天,除了简单的玩起来,但是对于处理大型复杂的task`还是没有太多想法。 能否指点一下。 谢谢

558

#51楼 @1272729223 现在这些资源我们是通过各种 webpack loader 来做,如果再复杂点,直接组合各种 shell 命令。参考 http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/

2909

#52楼 @camel 嗯,谢谢,这个人的那两篇文章我之前也搜到过了,看他写的还是蛮复杂的,如果简单的任务直接写在scripts属性里面似乎更方便,但是如果复杂的,我觉得还是直接写在Makefile里面更好(又要学写Makefile了)。

我再研究研究,不过方向基本定下来朝这个方向去了。

54楼 已删除
6553

awesome dude

96

呵呵哒

14154

VanillaJS 确实强大无匹

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册