Redux“七宗罪”
React+Redux目前已经成为了前端开发领域内较为主流的一种架构模式。其中React负责页面渲染,Redux负责管理所有的业务数据,如下图所示。引入redux确实能够很好的将数据与UI解藕,让React组件做到最大程度的复用性,但也带来了很多问题,这些问题都一定程度上降低了业务开发效率。以下详细探讨redux最主要的7个问题,简称“七宗罪”。
一 过多的文件
众所周知redux由三个部分组成:store、action、reducer。在使用redux时,当我们开发一个页面,我们就需要定义所有和这个页面逻辑相关的action。在处理业务数据时,我有由需要给每个页面或者时某种资源定义相应的reducer,久而久之,我们的项目里就有了许多action和reducer文件。过多的文件不仅增加了开发成本还会导致开发者在进行业务开发时不断的切换文件,降低了开发效率。二 业务逻辑割裂
redux框架中使用了reducer这一函数式编程的工具来进行数据管理,对获取到的数据(用户通过UI交互产生或后台数据返回)进行加工和保存。在前端开发中的业务逻辑一般包含了四个部分:收集数据、发送请求、接收请求、处理数据,如下图所示,这四个步骤一般出现在一个文件里,相对容易修改和维护。而redux把处理数据的逻辑单独抽离出来放入了reducer中,一定程度上增加了业务逻辑开发流程,让开发者必须定义好reducer中接受数据的格式,并且需要经常在不同文件中切换,造成了业务逻辑割裂。三 不必要的消息机制
在使用redux框架的项目中,涉及到store中数据更新的都需要通过发送一个action触发,这是一种典型的消息机制驱动的软件系统设计。消息机制在大型项目中解藕不同模块,提高可测试性和可扩展性方面都有不错的表现,但在一些小型项目中确没有起到什么本质性的帮助,反而需要开发者创建不同类型的action并定义action中payload的格式,增加了业务开发的整体流程。redux的本质是一个数据流管理工具,action的引入让系统毫无选择的被设计成消息机制驱动,对开发者不太友善。四 强制语法
redux的reducer的写法必须符合特定的格式,即每个reducer函数都必须返回一个新的对象。我们翻看一下源码不难发现,作者在这里才作用了比较对象地址来进行判断,如下所示。这种强制的语法不仅开销巨大,同样对开发者不太友善,一旦忘记这个约束就会造成业务逻辑错误。for (var _i = 0; _i < finalReducerKeys.length; _i++) { var _key = finalReducerKeys[_i]; var reducer = finalReducers[_key]; var previousStateForKey = state[_key]; var nextStateForKey = reducer(previousStateForKey, action); if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(_key, action); throw new Error(errorMessage); } nextState[_key] = nextStateForKey; hasChanged = hasChanged || nextStateForKey !== previousStateForKey;}
五 庞大的计算开销
我们继续查看上面的redux源码,当一个action被dispatch出去后,reducer是如何被执行的呢?注意到源码中遍历了所有的reducer并逐个比较返回的对象有没有改变。这就意味着任何一个action都会触发所有的reducer被执行一次,其中的计算开销是显而易见的。六 陡峭的学习曲线
redux作为一个前端数据流框架,内容较多,学习成本是相对较高的。redux中的store和reducer的使用方式是典型的函数式编程的方法,这对于习惯了面向对象编程的开发者来说需要一定的学习成本。此外action这种消息类型的开发模式对于前端开发者来说也相对陌生,需要一定的学习时间。七 不成熟的生态
目前围绕redux的相关技术比较多,主要都是redux的一些中间件,比如: redux-promise、redux-observable、saga等等。redux-promise、redux-observable都能解决异步数据的问题,但对业务开发的实质性帮助并不大。saga虽然功能强大但相对较重而且目前主要使用的仅仅是side effects部分。总体来说围绕redux的相关框架都不是特别成熟,尚不能对业务开发起到非常大的帮助。结尾
上文总结了redux的“七宗罪”,前端数据流框架的核心任务就是管理组件之间需要共享的数据,及时触发组件的重新渲染,这点在如今的前端架构中是非常重要的一环。redux的store能够很好的完成这一点,但引入reducer和action却带来了很多问题,降低了项目整体开发效率。那么一个合格的数据流框架究竟应该是怎样的呢?在下一篇文章中我会详细介绍我的解决方案-