浅谈从React到Redux

关于redux的发展,其实我也不太清除,似乎使用React的都会过度到Redux,大概算是React的全家桶之一吧,这里在了解Redux之前,不妨先了解下React设计应用的一些特性:

React 算是V层框架,它的组件化开发和单向数据流构特性构成了它设计的核心思想,组件化开发,将一个页面划分成多个组件,独立开发每块功能独立的组件 ,使得页面灵活可插拔可复用,然而组件的独立划分也必然会带来组件间的数据交互问题,因此对应提出了单向数据流的特性,要求设计好state数据结构,并放置在合理的位置,使得数据最大化的单向流动,然而尽管如此,在实际开发中,我们仍避免不了使用反向数据流,详见thinking React


一般来说,React的这两个特性,基本能合理设计并开发出许多结构不错的应用,但随着应用的规模庞大,把state作为数据层,就需要多个数据层(state)对应多个组件(view) ,那么假设state和view交互构成了如下数据流:

随着应用的庞大,一些反向数据流的存在就会造成错综复杂,不可预测的问题。

然而在Redux认为,用户在view层对数据的操作只能发起action,也就是将上面的数据流结构转换为如下结构:


从上图可以看出,引入了actions,从而将错综复杂的数据流变成了单向数据流(这里暂时不管圆圈里面是什么),进而强化了React的单向数据流的核心思想。

因此,引入了redux使得数据的变动变得可追溯,结构更清晰。


有了上面的过度后,接下来就该讨论,redux是如何做到这种数据流动的,关于redux的设计核心,这里先设计这幅循环图来直接解释:


上图是一个比较好解释redux数据流的循环图,这幅图里有五个部分五个箭头,这里就先简单介绍这五大块,再对每块具体操作详细分析。

1. 有defines箭头可以看出,只有State的变化才会引起UI的变化。

2. 由triggers箭头可以看出,UI 只能统一触发 Actions操作。

3. 由sent to可以看出,Actions需要分发(dispatch)到Reducers上去决定如何执行。

4. 由Updates可以看出,Reducers可以更新Store中的状态,然而Store中的状态是什么呢?

5. 由contains可以看出Store可以认为是State的集合,也就是说,Reducers决定着State如何改变,Store用于统一化管理State。


那么Redux这种循环流向的特性,也就决定着在设计应用流程上应该遵照的统一化步骤:

1. 首先是actions,actions简单来说就是用户操作UI界面能发起的动作,它其就是用json对象定义的,其中必须要有一个type字段,指明是哪种类型的操作,type字段的值一般是字符串,使用字符串常量会更好一些,同时可以传递该操作需要传递的参数。

2. 其次需要设计的是Reducers, Reducers其实是用来决定不同类型(type)的actions需要怎么修改state,(这也就意味着在此之前最好先考虑一下state结构的设计),Reducers必须是一个纯函数,它接受旧的state和actions,返回的是新的state,在redux-react中,可以根据类型不同设计不同的reducers,这也就对应着state结构中不同的字段了,最后将他们combine。

3. 对于combine的reducers,需要将其注册到统一且唯一的store中去才能达到统一化管理的效果,然而要想在react中引入store并在整个组件中使用,就需要react-redux提供的Providers组件了,用它来让React组件中共享store。

4. 关于UI组件,这里放在最后,其实也可以不这样,先设计UI组件也是可以的,只是这里要讨论state将要如何决定UI组件的改变,而且UI组件又如何发起action,这两步是打通整个循环的最基础也是最重要的一步,为了区分UI组件和交互相关,在Redux中提出了两种不同类型的组件,Components组件和Containers组件,两种组件可能对应于同一页面同一部分,但两者负责的任务不同,简单来说Components组件只负责展示,传递什么参数就渲染什么内容,而Container组件负责数据流入流出,决定组件需要什么数据和能触发什么actions,从某种模型上来说,Containers或许就是Components外层的一个包装,因此在某些特殊的情况中,可以将Components合并到Containers中去。

这里也展示了容器组件和展示组件之间的区别



因此对于Components组件来说,所有的数据都是通过组件的属性props来决定的。

对于containers组件来说,就需要决定哪些state的流入和哪些actions的流出或者说是分发(dispatch),因此也就有了两个函数  mapStateToProps和mapDispatchToProps,mapStateToProps提供两个参数,一个是整个state数据,另一个则是原始属性值Prop,它的返回值即是需要映射到组件数据(用于渲染页面)的state数据。

mapDispatchToProps提供一个dispatch函数参数,它其实是store的函数,用于分发action到reducers中去。mapDispatchToProp返回值就是一系列的方法,用于映射用户对UI的哪些操作对应需要分发哪些actions。

最后需要做的是将容器组件和展示组件绑定起来,这时候需要用到的方法就是react-redux提供的connect方法,connect方法是一个高阶函数,第一阶函数需要两个函数参数,其实就是上面所说的那两个函数,这两个参数是有顺序的,但又不是必须的,如果不需要传递null即可,第二阶函数则需要传递这两个函数绑定的组件,就像上图那样把组件装进容器里合并在一起,这样我们最中需要渲染展示的页面是connect后的组件,而不是之前所说的展示组件了,因为connect后的组件才会有数据流的传递,才能享受redux提供的数据状态循环流动的便利。

你可能感兴趣的:(浅谈从React到Redux)