本篇将介绍redux跟react-redux。这里打算是介绍这两个插件在react项目中的运用。redux是可以在其他库中使用的。
前面使用react开发项目,是可以实现大部分需求的。但是react毕竟是一个实现视图层的框架,它在数据层的实现还是存在一些不足的。比如当项目较大,需要使用大量的数据,父子组件之间的数据通信特别频繁的时候,性能就会直线下滑;当数据发生改变的时候,就无从得知数据是从哪里发生改变的。
redux作为一个应用数据流框架,它的最大的特点就是应用状态的管理,它用一个单独的常量状态树store保存整个应用的状态。这个状态树不能直接被改变。
我们分析一下。如果没有redux,react组件的所有状态state将各自存储于组件中,一旦遇到不同父组件的组件之间的通信问题,需要把数据先传到能使两个组件通信的上层组件,然后在下发到另一个组件。而如果使用redux,则数据都存储在常量状态树store中,所有组件获取状态数据都从store中直接获取。而组件需要修改状态数据时,只需要直接修改store中的数据,其他组件就会获知store的变化并自动重新获取状态。这样可以减少组件之间大规模的通讯消耗。
redux工作流程
我们了解了react的组件components跟redux的常量状态树store,那他们是怎么串连起来,是怎么样的工作流程呢?
这里需要考虑三个场景,一个是components需要修改store中的数据,一个是store中实现数据的更新,还有一个就是store的数据更新之后新状态同步到components中。
最主要是前两个场景。这里需要引入redux中两个概念。
actionCreator
因为常量状态树store的状态数据不允许直接修改,所以当components需要修改store中的数据时,需要通过actionCreator中的action去让store做数据的更新。
actionCreator是一个action的集合,这个集合中包含了各种用于申请修改的action。这个action需要包括修改数据的类型跟需要修改的数据。在components发出store.dispatch(action)之后提交给store,完成修改申请。
reducer
当store得到action时,它本身没有什么方法可以修改数据,所以需要用到reducer来实现状态的更新。store会把当前的state跟前面接收到的action传给reducer,reducer会根据传入的action类型进行状态更新,然后再返回新的state。
组件的状态更新
关于最后store的数据更新之后新状态同步到components中,阮一峰的《Redux 入门教程(一):基本用法》中有提到,当store中state发生变化后,store会调用监听函数,监听函数就可以更新组件中的state,组件就可以重新渲染页面。
react-redux实战
安装react-redux
在react项目中,引入react-redux还需要引入redux:
1 | npm install redux --save |
这样在react项目中才可以使用react-redux。
创建store
先在项目中创建一个store的文件夹,然后在创建一个index.js的js文件。在这个js文件中写下以下代码:
1 | import { createStore } from 'redux'; |
首先,先从redux中引入createStore,然后通过createStore来创建一个store,最后导出。
创建reducer
上面我们已经完成store的创建,然后需要创建reducer来给store处理数据。在store目录下创建一个reducer.js的js文件。redux中,reducer其实是一个函数,所需要引入的参数为当前的state(preState)跟action,而返回的是一个修改后的state(newState)。一般初始化的时候,没有当前的state(preState),所以会先声明一个defaultState:
1 | const defaultState = { |
上面的代码中,先声明一个defaultState作为state的初始化状态,然后导出一个函数,这个函数中通过判断action.type来修改获得newState,然后返回出去。
创建之后,需要把reducer传入到store中,因此上面的index.js需要稍加修改:
1 | import { createStore } from 'redux'; |
创建actionCreator
actionCreator还是要强调,它是一个方法的是一个action的集合,这个集合中包含了各种用于申请修改的action。当然,把所有action都只在需要的时候再编写也可以,但是把所有action集中起来可以提高代码的可读性,可维护性。每一个action方法最终都是返回一个对象,这个对象包含有修改类型type跟需要修改的值。在reducer.js中,大家可以看到传入的action.type是会在switch语句中作为判断值,然后修改值则会在判断后做对应的修改。
在store目录下创建一个actionCreator.js的js文件,然后写入所有需要导出的action方法:
1 | export const action1 = (value1) => ({ |
在reducer中,action.type作为判断时,会再写一次。为了保证不出抄写错误,方便后期排查bug,一般还可以把actionType集中起来:
1 | export const actionType1 = 'action_type_1'; |
那么,在actionCreator中就可以改写成:
1 | import * as constants from './actionType'; |
组件中的使用
组件中使用一般分引入store,调用action申请及store修改订阅。
组件中会现在构造函数中引入store:
1 | constructor (props) { |
当状态需要修改时,通过store.dispatch()调用action:
1 | store.dispatch(actionCreators.action1(value1)); |
action方法返回对象将交给store,但是store不会处理,而是通过dispatch方法交给reducer处理。reducer接收到action后,会根据修改类型type对数据进行更新。在store的状态进行更新之后组件就需要更新。但是组件的状态更新还需要做一步操作,就是对store变化的订阅。这个订阅也是在constructor()完成:
1 | constructor(props) { |
以上就是对redux跟react-redux使用的总结。