理解Redux

昨天花了很久的时间,终于有些理解Redux了。根据官方的文档也做出了一个例子而且运用到我的项目中去。

关于Redux

对于我了理解其实Redux就是一个能整合所有数据的大的State,它方便了组件之间的数据交流,一般的组件数据都是自上而下的通过props进行传递,而这样做的后果就是造成,对于一个嵌套了很多层的组件来讲,这样的实现方式就会显得相当麻烦,最顶层的组件不得不通过一层层的props来去和目标组件进行数据交换,这样产生的后果是造成了大量了性能缺失。而且如果两个组件拥有各自的state,但是需要进行数据交流的话,通过props进行交流这种方法就不能实现了。

早期FaceBook通过Flux来解决这一个问题,React内部也有一个context的API来解决这种问题,直到后来Redux出现了,它基于Flux的设计理念,即Vevw层不允许直接修改应用状态,只能触发Action,应用的状态必须独立出来放到store里面统一管理,通过监听Action来执行具体的状态操作。
即View->Action->Store->View,这样视图组件的功能只是展示,Action用来分发事件,dispatcher接受Action来处理事件改变Store,Store的改变又是的View层重新渲染。
单向数据流是Redux的核心理念,所有的状态变化都可以被记录,跟踪,组件的数据只有唯一的出口及入口,这样程序显得更加直观,通俗的讲,找起Bug来比较容易(手动滑稽).

Redux的实现流程

再不考虑异步的情况下,Redux的实现方式十分简单,其实异步也不难。

Action

一般的流程首先是先创建Action,Action一般是一个对象,对象必须包含一组键值对,type属性,type的值必须是字符串,这并不代表type的值必须是字符串属性的,只要是输出的为字符串就行,比如字符串赋值的变量,一个函数的返回值为字符串也行,Action中也可以包含其他的值,一般都有什么值呢?请移步我之前的一篇博客关于Redux中的有关于Action的社区内规范。

Action的种类取决于你的组件内需要交互的种类有多少,一般在一个组件内,Action的种类应该相当繁杂,你可以写在一个Action.js中,当然你也可以写在你的各个组件内的action.js内,每个组件掌管自己的action,我们一般使用一个函数来生产Action,毕竟一个一个的写比较麻烦。

1
2
3
4
5
6
7
function Switch(index){
return {
type:'Switch',
index
}
}//这就是一个生产Switch的组件啦

上面的函数就是一个生产Action的组件,其中index是一个简写的方式,相当于{index:index}

Store

Store相当于是一个应用中最顶层的state的身份,它包含了一个应用内所有的数据,通过createStore()函数可以返回一个Store,通常一个应用内只能使用一个Store,所有的应用数据都在这个Store中,每个组件通过’connect’这个Redux中的API来获取Store中的一些数据,connect类似于筛选器这么一个功能,他接受一个函数,这个函数一般用来返回Store的数据所用的,你可以在这个函数内选取自己需要的的数据值,举个例子吧。

1
2
3
4
5
6
7
8
9
10
//假设Store的数据长着个样子
Store = {text:'hello',name:'world'}//不是真实的Store哈
function select(state){
return {
hello:state.hello
}
}
connect(select)//这样组件就会拿到这个Store的一个hello属性的值,并将它返回给组件

Reducer

Reducer类似于加工厂的身份,他接受两个参数,一个是Store,一个是action,Store是我们通过createStore()这个API得来的,reducer将获取的两个参数进行加工,然后就会返回一个新的Store。reducer会通过比对Action中的type值来返回不同的结果,所以这就是为什么我们需要给Action加type键值对的根本原因。下面就是一个有关于reducer的流程演示(不代表真是代码)的伪代码.

1
2
3
4
5
6
7
8
9
10
11
12
//假设我们的store长成这样
Store = ['校长','班主任','班长','同学']
action = {type:'Switch',index:1}
function Reducer(state=Store,action){
switch(action.type){//开始比对action.type
case:'Switch':
return state:Object.assign([],state,state[atcion.index]='大王')//返回一个新的state
}
}

Reducer函数有点类似于React中的setState,它不允许你直接修改Store的数值,他只能让你返回一个新的Store,所以尽量避免直接在Reducer函数内直接修改Store这样的操作,如果Store是一个数组,那么我们就使用slice这样的方式增删改查,如果Store是一个对象,我们可以使用Object.assign()来进行操作,当然我们也可是使用immuatble.js来进行Store的修改,只要记住一点,Reducer不能直接修改Store的属性就好。

这是因为Redux自身的diff算法造成的,如果我们直接修改Store,就会使得Redux自身监听不到Store的修改,从而无法让整个组件重新渲染。
还有Reducer是一个纯函数,关于什么是纯函数,请移步阮一峰的Redux教程。

store.dispatch()

store.dispatch()是View组件唯一能发出Action的方法,前面讲的Reducer接受一个Action不是吗?所以如何将我们所需要的Action发射出去呢,这就需要我们使用store.dispatch()来发送给Reducer了,比如点击一个页面元素,我们就必须把这个dispatch()绑定在这个元素上。看如下一个伪代码。

1
2
3
4
5
6
7
8
9
10
11
12
export default const action = {type:'Switch',index:1} //action.js
export default function Reducer(state=Store,action){
switch(action.type){//开始比对action.type
case:'Switch':
return state:Object.assign([],state,state[atcion.index]='大王')//返回一个新的state
}
} //reducer.js
const Store = createStore(['校长','班主任','班长','同学']) //Store.js
<h onClick = {store.dispatch(action)}>点击我</h> //component.js

上面的代码就是整个改写的过程,但是实际操作肯定比这个要复杂的多,你可以在网上找相关的资料来看,这个文章只是告诉你,Redux的大体流程,在脑海中有个相关的概念,之后在理解Redux就没那么困难了

BYE BYE