flux,redux,react-redux都有一个共同的特点就是react的状态管理工具,因为之前有学习过Vue,在学习flux,redux,react-redux的时候就轻车熟路了。话不多少,我说一说他们的使用方法和流程。
首先是flux,算是react一个基础版的状态管理工具,代码量最多,一共有四个功能模块。
视图模块View:用来展示数据以及收集用户操作改变的数据,可以划分TodoController组件和View组件两个部分,TodoController组件是专门用来写业务逻辑的,而View组件是专门展示数据。两个组件之间功能分得如此清楚是因为方便后期调试,但是很多人也会认为很复杂,因为组件之间需要通过props来回传值,增加了操作繁琐性。
驱动模块Action:Action是一个对象,对象里面用来存储属性方法,因为要接收View传递过来的参数,所以Action对象里面都是方法,用来接收参数,方法会返回一个对象,这个对象的作用是用来驱动Dispatch模块进行数据改变。这个对象的格式为 {actionType:'ADD',text:[形参]}
中心模块Dispatch:Dispatch的地位就相当于任务中心,接收Action传递过来的对象参数,并利用switch语句对动作类型进行判断,然后根据动作类型来调用Store里面的方法,相当于通知Store制定动作。
仓库模块Store:Store汉语意思有存储,仓库,商店的意思,Store作为一个仓库,它的本质作用就是存储应用状态(说白了就是我们想要操作的数据),Store里面可以存储不同状态,但是状态越多,我们返回的数据就会更复杂,在后期我们维护整个应用时就会变得很复杂。flux里面的Store就是专门用来存储状态和操作状态的方法,并且规定只有Store能够直接操作状态,改变状态。那Store又需要哪些基础的方法呢?除了操作数据的方法,Store里面应该还要包含监听状态改变的方法,有监听就必须有接收者,还得有一个返回状态的方法,便于外部取Store里面的应用状态。
四个模块都说完了,那我通过一个简单的TodoList效果(列表的添加删除)简单诉说一下flux的工作流程。首先是完成视图模块View组件的注册,这个地方我采用行为和结构分离的模式来写,也就是把View模块分为一个容器组件(Controller)和一个视图组件(View),两个组件通过props传值,子组件向父组件传值的方法,有必要在这里说一下:
子组件:
父组件:
接下来,我的业务逻辑会在父组件里面书写,这时候Controller就像是一个任务发布者,它会通过Dispatch对象的dispatch方法来发布任务 (Dispatch.dispatch(Action.addItem(msg))),其中Action.addItem就是Action对象的属性方法,Action.addItem(msg)==>{actionType:'ADD',text:msg}。
下一步:Dispatch对象就会接收到Controller提交的任务对象,actionType就是任务类型,text是任务内容,根据任务类型,Dispatch就会调用相应的Store的方法,每一次调用Store方法都会导致应用状态发生改变,这时候我们需要通过Store.change()来通知监听者状态发生改变。Dispatch的作用其实就是这么简单,然后操作走到Store对象,Store里面有一个广播状态改变的方法change(),有一个通知Controller状态改变的监听函数listenChange(callback),callback就是监听函数触发的回调函数,Controller组件通过在钩子函数componentDidMount()里面监听状态改变的函数(Store.listenChange(callback)),回调函数里面应该更新Controller组件的状态 值。我们如何从Store里面拿到数据,应该是通过一个方法返回应用状态,就是上文提到的getAll()方法返回应用状态值。
Controller通过Store.getAll()方法获取值,然后通过props把属性传递给View视图组件,最后在视图组件里面展示数据。
讲了这么多的flux,下面redux和react-redux就不用讲太多,工作原理都差不多,就是比flux的过程更加简化了,首先先来讲讲redux吧,redux的主要功能模块是Action Store Reducer 和View模块,这里的View和flux的View如出一辙,我们的行为逻辑可以在View组件里面书写,省去了传值的复杂操作。
你可以看到的是Dispatch模块消失了,可以想象原因是什么,Store改造升级了,Store自带了getState()方法用来获取状态,还自带了subscribe()方法用来取代flux的手动监听函数,取代了Dispatch,也不用在Store里面操作数据了。
增加了一个模块Reducer,通过Reducer来处理数据,Reducer是一个函数,它有一个特点就是输入什么就返回什么,也就是你不能直接操作参数,只能是通过另外赋值的方式来进行数据操作,然后返回新数据,神奇的是,明明返回的不是State,但是State好似能记录这种改变。
还是上面的那个例子,我们flux通过Dispatch.dispatch()方法来发布任务,现在我们通过替代品Store来发布任务(Store.dispatch()),Store对象的生成方法也改变了 以前是 Store = {},redux利用了createStore方法生成Store实例(new createStore(Reducer)),你不需要管Store有什么东西,也不用自己手动生成Store了,只需要关注Store里面一些重要的API,比若说getState(),subscribe()。下一步就是生成Reducer。
Reducer是一个函数,它的参数就只有两个,一个应用状态state,你可以提前对形参赋值,规定state的属性,另一个参数就是action对象,我们需要判断action对象的type属性值,然后根据值进行不同的操作,增删改查都ok的,但是要注意一点,就是不能直接操作state,采用赋值的形式,返回一个新的state。最后就是View组件展示数据了。
最后一个状态管理方法 react-redux,看名字你就能知道,他其实和redux差不多,然后这种状态管理工具是为了管理无状态组件的数据的,因为无状态组件没有this,也没有state,只有props,所以我们需要想办法在props上操作数据,或者是利用props对数据进行操作。在这里我通过讲述例子讲解react-redux和redux的差别。
首先我们先注册无状态组件,无状态组件其实就是一个纯函数,不是对象,所以他没有render函数,直接通过return写模板,然后也没有this和state,我们需要在外部定义按钮触发的函数,在纯组件里面没有state,也不能定义方法,那我们只能把state,和方法遍历添加到props,作为props对象的属性,通过定义两个函数(mapStateToProps,mapDispatchToProps),我简单书写一下代码:
const mapStateToProps = (state) =>{return{list:state}}
const mapDispatchToProps = (dispatch) =>{return{add:(msg)=>{dispatch([action])}}}
然后我们直接在本文件里面生成store对象和reducer对象,方法和redux一样,然后利用react-redux里面的connect方法和Provider组件标签,利用connect方法把mapStateToProps和mapDispatchToProps以及最开始的无状态组件合并成一个组件新的组件,方法如下:
const NewIndex = connect(mapStateToProps,mapDispatchToProps)(Index)
然后把store对象作为Provier的props对象,里面嵌套newIndex,然后生成一个新的组件,并导出就ok了。
这是在的第一篇文章,没想到竟然没有写代码的工具,让我很难受,没法把源码发上去,这篇文章仅供参考,这篇文章里面不会有太多的专业词汇,毕竟我不算是计算机专业,算是跨专业跨行业,以上都是我自己对于flux的理解,写这篇文章的更主要的目的是为了记录自己的学习体悟。