前端的浪潮一叠叠袭来,带走了jQuery,带走了backbone,带来了react,带来了redux,但是面对层出不穷的前端技术,我们应该何去何从呢?近一年来笔者的也发生了同样的变化,技术栈从.net+backbone+requirejs+grunt变成了nodejs+react+webpack+gulp,一系列的变化也让笔者对整个过程,整个闭环的工具链有了一些自己的感受和理解,于是有了今天此文。

  其实react出现得很早,但是笔者所在的唤作“大象转身”的大公司,所以内部技术的迭代,并不像业务迭代那么的频繁,毕竟大多数公司奉行的依旧是技术为业务服务的原则(诚然,技术没有经济利益的产出,则没有理由不信奉,不过这又是另一个话题,权且按下不表)。不过也就在去年,笔者由于一些工作上的变动,开始全面的接触起了react起来,于是念上心头,我们为什么要用react呢?

  其实,谈到react,可能最先映入眼帘的就是它对于dom的托管,virtual dom技术的出现也一定程度上封装了之前纷繁复杂的dom操作,而且也降低了使用门槛(有关浏览器内部渲染原理),虽然这也是有副作用的,但是它相较于backbone,省去了大量的dom交互的过程,对于每位前端er都是一件很了不起的事情;不过,相比之下,笔者其实更中意它的设计中的数据流的思想,数据能够受到约束之后,页面的状态不再像之前的时代那么混乱无序,一切归于平静是多么美好的一件事情。。但是,这种好日子其实并不长久,在应付小规模应用的时候,有约束的数据流向和传输也许并没有什么副作用,但是项目规模扩大之后,一级一级的状态/属性传输却显得特别的臃肿和低效,如下图:

  

  当我们的组件树只有1层或者2层的时候,想从最上层透传属性还是很容易的事情,但是当组件层级越来越多,比如上图,从底层父组件传递属性到达最末的叶子组件,整个过程的传输在代码上就显得相当的冗余,而且如果多个组件依赖于一个共同的属性,局部变化引起的全局变化很容易又会导致状态震荡,这也是令人倍感头疼的问题,所以redux就应运而生。

  react官方最先推出的方案是flux,随后见贤思齐的将其替换为了redux。其实react中强调的单向数据流几乎是需要依托redux才能实现的,当接入了redux之后,整个数据流动就变成了以下这个样子:

  

  所有的状态变化都拘束到reducer(s)中进行,修改统一的数据源,然后再自上而下的重新分发,减少状态/属性传递的成本,也从根源上杜绝了状态震荡,而且redux将数据从react中分离,则理论上所有的react component都可以是无状态组件,那么渲染性能还能够得到进一步的提升。

  看到这么精巧的设计,笔者饶有兴致的研究了一下源码,并且尝试着自己也实现了一个简单的redux,其实redux的源码也非常的简洁:

index.js
createStore.js
compose.js
combineReducers.js
bindActionCreators.js
applyMiddleware.js

  主要文件一共就6个,用得最多的就是createStore和引用了职责链模式的applyMiddleware,createStore中大量的体现了函数式编程的思想,刚开始读起来确实有些吃力,而且js似乎并不是一个很好的实现函数式编程的语境,不过瑕不掩瑜,短短百行不到的代码,却解决了react没能解决的一个很棘手的问题,这也确实是令人惊讶的;另外,相信使用过koa的同学对于职责链模式其实并不陌生,特别是还看到了那个蜜汁compose,那种剥洋葱的调用结构极大的提高了我们在nodejs 写webservice时的扩展性,也跟我们后续的维护提供了一定的便利。

  不过本文意并不在介绍它们的内部原理,让我们回到正题。说了一大堆redux的优点,那么它有没有缺点呢?诚然,事无绝对,必有正反。虽然redux提供了很大的方便也弥补了react的一些机制不足,在技术方案上,似乎并没有什么问题,但是在实际使用时,由于它自身的松散耦合的特性,导致了实现具体功能时多种多样的方式,而不同的人的理解又会导致不同的实现,举两个笔者所在的团队的例子:

  一个是有关数据统计和异步请求的代码究竟应该写在哪的问题。不同的业务场景不同的人,不同的实际情况,很有可能会让我们在实际操作时,将action和reducer混淆使用,这样本来是为了降低维护成本而剥离产生的action却增加了我们的额外成本,这其实是得不偿失的。

  另一个是关于状态注入时状态的多少问题。注入少了,之后的需求变更又需要频繁改变代码,注入多了又会导致组件的频繁更新,且注入方式相当的随意,对后续维护也是一件非常吃力的事情。。。

  其实这样的例子还有很多,归根结底redux是一种思想,而且还是一种很灵活的思想,它给了使用者很大的自由发挥的空间,但是在社会化的协同工作时,过多的“自由”却又意味着“不自由”。 

  其实时代的变迁,历史的演进,新旧事物的交替其实是提现了人类思维方式的变化和面对的场景的变化。当初我们只需要dom操作就能完成页面,所以jQuery就足够了,但是现在随着前端的不断发展,体验要求、功能要求越来越高,越来越多,原始的简单页面维度的应用已经不能满足了,于是,react或者其他的类virtual库才会应运而生,然后新问题出现了,再去造新的轮子,然后,历史也便形成了。

  但我们仔细想来,就会发现,我们所造之物,其实永远都不是一个囊括所有问题答案的方案,我们给出的,不过是针对某一个历史时期的某一个场景的某一个局部最优解而已,问题在变化,答案也在变化,不变的,也许只有时间亘古不变的流逝,以及我们那颗需要永远保持运动变化的心。

  

【js】为什么要使用react+redux的更多相关文章

  1. Immutable.js 以及在 react+redux 项目中的实践

    来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...

  2. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  3. react+redux教程(六)redux服务端渲染流程

    今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...

  4. react+redux教程(五)异步、单一state树结构、componentWillReceiveProps

    今天,我们要讲解的是异步.单一state树结构.componentWillReceiveProps这三个知识点. 例子 这个例子是官方的例子,主要是从Reddit中请求新闻列表来显示,可以切换reac ...

  5. 基于React,Redux以及wilddog的聊天室简单实现

    本文主要是使用ReactJs和Redux来实现一个聊天功能的页面,页面极其简单.使用React时间不长,还是个noob,有不对之处欢迎大家吐槽指正. 还要指出这里没有使用到websocket等技术来实 ...

  6. react+redux教程(四)undo、devtools、router

    上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...

  7. react+redux教程(三)reduce()、filter()、map()、some()、every()、...展开属性

    reduce().filter().map().some().every()....展开属性   这些概念属于es5.es6中的语法,跟react+redux并没有什么联系,我们直接在https:// ...

  8. react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware

    今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...

  9. angular开发者吐槽react+redux的复杂:“一个demo证明你的开发效率低下”

    曾经看到一篇文章,写的是jquery开发者吐槽angular的复杂.作为一个angular开发者,我来吐槽一下react+redux的复杂. 例子 为了让大家看得舒服,我用最简单的一个demo来展示r ...

  10. 【原】react+redux实战

    摘要:因为最近搞懂了redux的异步操作,所以觉得可以用react+redux来做一个小小的项目了,以此来加深一下印象.切记,是小小的项目,所以项目肯定是比较简单的啦,哈哈. 项目效果图如图所示:(因 ...

随机推荐

  1. [luoguP1097] 统计数字(水)

    传送门 这么水的题,也只有提高组第一题了吧 代码 #include <cstdio> #include <iostream> #include <algorithm> ...

  2. codeforces 362A找规律

    刚开始以为是搜索白忙活了原来是个简单的找规律,以后要多想啊 此题是两马同时跳 A. Two Semiknights Meet time limit per test 1 second memory l ...

  3. [K/3Cloud]将JSON字符串反序列化为C#动态对象

    using Kingdee.BOS.Util; string errString="{/"Row/":1,/"PageId/":/"1234 ...

  4. 开发辅助网站---programcreek

    开发中让我们事半功倍的工具网站,开发中经常遇到api如何使用,很好的解决这个问题.java代码api案例网,提供最简单的demo,很不错分享一下,大家可以用用. http://www.programc ...

  5. 姓名与ID(codevs 1027 未结题)

    题目描述 Description 有N个人,各自有一个姓名和ID(别名).每个人的姓名和ID都没有重复.这些人依次进入一间房间,然后可能会离开.过程中可以得到一些信息,告知在房间里的某个人的ID.你的 ...

  6. 【HDOJ4322】Candy(费用流)

    题意:给N个孩子分配M个糖果. 有一个N*M的矩阵表示孩子和糖果的关系,若第i行第j列的数是1则表示第i个孩子喜欢第j个糖果,反之不喜欢. 已知,若一个孩子被分配到他喜欢的糖果那么他将获得K的快乐值, ...

  7. 使用MediaPlayer播放、暂停、停止音乐

    package com.pingyijinren.test; import android.media.MediaPlayer; import android.os.Environment; impo ...

  8. HDU——2063 过山车

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  9. 应用CLR的线程池

    大家都知道这个线程的建立和销毁都需要很大的性能开销,当有比较多且不同的任务需要完成时,可以考虑使用线程池来管理这些线程.在以windows NT为内核的操作系统上每个进程都包含一个线程池,在线程池中存 ...

  10. JAVA调用动态链接库(dll)

        菜鸡爬坑 基础知识  因为某个东西的keygen我只会在win下生成!! 所以只能出此下策!!之前一直是android下用jni调用so文件,现在试下java在win平台下调用dll 首先还是 ...