欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
更完美的状态管理方案
 
过去的几年,中台领域出现了很多非常优质的UI组件库,比如Ant.Design, Element-UI等,这些组件库解决了过去前端工程师所面临的还原设计稿成本高的问题,通过采用统一的设计风格的UI组件,就能让前端工程师无需再专注于切图和写CSS,而是更专注于页面逻辑的实现。
 
在页面逻辑的实现层面,UI组件的状态管理也有了很大的发展。随着Flux的提出,再到Redux,Mobx等,使用一个状态管理库来管理一个应用的状态已经成为了前端主流,甚至在最新的React中,还会有UseReducer这样源自Redux的API出现。
 
而对于状态管理,社区也衍生出两种完全不同的思路。
 
状态管理的两极分化
 
一种是以Redux为主导的不可变数据流的方案,通过让整个应用共享一个全局的Store,并且强调每一次数据更新都要保证State完全不可变,以及完全避免使用对象引用赋值的方式来更新状态这样的方式来保证对页面的数据操作,让整个应用具备可追溯,可回滚,可调试的特性。这样的特性在面对代码如山一样的大型复杂应用,有着非同一般的优势,能够快速来定位和解决问题。
 
不过Redux这样的模式也存在一定的弊端,首当其中的就是它要求开发者要完全按照官方所描述的那样,写大量的Action,Reducer这种的样板代码,会让代码行数大量膨胀,使得开发一个小功能变得非常繁琐。使用单一的State来管理就需要开发者自己去完成State的结构设计,同时不可变数据状态管理仅仅是Redux所强调的一种思想和要求而已,由于并没有提供有效避免对象引用赋值的解决方案,就需要开发者时刻遵守这种模式,以免对不可变造成破坏。
 
因此Redux这种设计模式固然有效,但是过于繁琐和强调模式也是它所存在的弊端。
 
而另外一种则是与Redux完全相反的思路,比如Mobx。它鼓励开发者通过对象引用赋值来更改状态。Mobx通过给对象添加Proxy的方式,获得了每个用户每个React组件所依赖的属性,这样就拿到了对象和组件之间的属性映射关系,这样Mobx就能依据这些依赖关系,自动实现组件的更新。使用Mobx之后,State的很多细节都交给Mobx进行管理,也就不会有Redux那种State设计的工作了,同时也就不存在像Redux那样,编写大量的样板代码,而是直接修改状态数据就能达到预期的效果。
 
Mobx这种的思想和Vue的机制非常类似,同时也都存在同样的一个弊端——由于没有状态的副本,无法实现状态的回滚。数据之间的关系捉摸不清,更新的实现完全被隐藏在Mobx内部,对开发者不可见,当状态复杂之后,就会造成调试困难,Bug难以复现的问题。
 
Mobx这种设计模式能在早期能极大提升开发效率,但是在项目后期就会给维护和调试造成一定的困难,造成效率的降低。
 
可见,在状态管理不可变数据和可变数据都各有各的优缺点,貌似是鱼和熊掌不可兼得。那么问题来了,是否存在一种新的技术方案,能够结合Redux和Mobx的优点呢?
 
有关Redux和Mobx之间对比的详细的内容,可以继续看这篇文章:https://www.educba.com/mobx-vs-redux/
 
简单而又可靠的状态管理
 
在大型复杂应用开发这种场景下,Redux可靠但是不简单,Mobx简单而又不可靠,因此就需要找到一种简单而又可靠的状态管理方法。
 
Redux的可靠在于它能够让状态可回溯,可监控,使用单一的状态能降低模块太多所带来的复杂度。Mobx的简单在于它使用方便,对写代码没有太多要求,也不需要很多的代码就能实现功能。
 
对于大型复杂应用来说,状态可回溯,可监控这些特性是重中之重,有了它才能让整个应用不会因为太复杂而失控。因此优化的方向就被转化为:能否借鉴Mobx这种简单易用的思想,来降低Redux的使用成本。
 
在使用单向不可变数据流这种背景下,降低Redux的使用成本需要往以下三个方面发力:
 
combineReducer的使用会让开发更繁琐,因此需要避免每次开发都需要进行State结构设计
 
每一次数据操作都要写Action,Reducer也会让开发更繁琐,因此需要避免编写大量的Action,Reducer
 
不是所有人写的Reducer都能保证State修改不可变,因此需要一种替代方案来修改State
 
针对以上三个方面,我认为可以采取以下方法来进行解决:
 
利用将组件之间的结构关系映射到State,就能在一开始就推断出State的结构,进而自动帮助开发者完成combineReducer这样的操作。
 
将多个Action进行合并,为开发者直接提供通用Action的方式,多个Action之间利用参数来进行区分,以解决Action过多的问题。
 
为开发者封装状态操作的API,在内部实现不可变的数据操作,避免开发者直接接触到State。
 
有了上面三个基本的思想,接下来就是要思考如何才能够和现有的Redux架构进行整合。
 
像Mobx一样去使用Redux
 
首先,第二个和第三个方法可以被整合成一个API——一个通用,保证状态不可变的状态修改API。这样就和Mobx直接改了数据状态就更新的操作很相像了——调用这个API就把修改状态搞定了。
 
而对于第一点,熟悉react-redux的同学都知道,Redux中的State,是通过编写mapStateToProps函数来将状态映射到组件的Props上的。而mapStateToProps函数的参数却是整个Redux的State,想要将它映射到组件中,还需要完成从State取值的操作。而当我们在一开始设计状态的时候,依然需要去想个名字来完成整个状态的结构设计,前后一对比,仔细想想后会发现,这一前一后都是需要一个Key才能完成,为何不用同一个Key呢?这样一个Key既可以完成Redux的State中,每一个Reducer的划分,也可以完成mapStateToProps的时候,属性的读取。
 
所以我们只需要将这个的一个Key放到一个组件的属性上,通过组件的挂载来完成过去需要combineReducer才能完成的状态划分,然后再mapStateToProps的时候,同样依据这个属性,完成State到Props的映射。而且通过这样的方式,整个State的结构都完全可以在组件上进行控制了,也就不需要再去使用combineReducer这样的API了。
 
通过上述的讲述的方法,我们就可以将它们封装起来,做成一个React组件,让这个组件来帮助我们管理状态,并且通过这个组件的API来修改状态。这也就是RCRE中,Container组件背后的思想。
 
Mobx的简单不光光在于开发者不需要思考如何去更新和管理状态,它还有一个很大的优势在于,你可以再任何一个地方都可以直接去修改状态。相比目前Redux中,一些值和函数都采用props进行传递这种繁琐的方式,Mobx这样的功能会让人感觉方便不少。
 
因此,即使现在有了Container这种可以帮助我们自动管理状态的组件之外,我们还需要一种类似于Mobx这样,可以绕过props也能传递数据和方法的设计。
 
React在16版本推出了新的Context API,这也是所官方推荐的一种跨props传递数据的解决方案。因此我们可以利用这个API,来实现在Container组件内部的任何一个地方,都可以自由读取状态和修改状态。也就是RCRE中,ES组件背后的思想。
 
总结一下,解决Redux使用成本高的问题的核心就在于,找出那些可以被重复利用,差异性不是特别大的地方,再加以封装,就能得到非常不错的效果。

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h63592.shtml