Redux是React全家桶的重要一员,以前在知乎上也看到相似的提问:该如何通俗易懂的理解Redux?
Redux是JavaScript的状态容器,Redux的概念简单明了: javascript
1. 应用中全部的状态都是以一个对象树的形式存储在一个单一的store中;
2. 当你想要改变应用的中的状态时,你就要dispatch一个action,这也是惟一的改变state的方法;
3. 经过编写reducer来维护状态,返回新的state,不直接修改原来数据;java
在React中,数据的传递主要采用state和props,props得由父级分发下来,而state是组件中可自行管理的状态,这意味着React并无让数据回溯的能力,数据只能单向向下分发,或者自行内部处理,举一个简单的例子,父组件可使用props向子组件传递数据,子组件能够经过触发回调函数来改变父组件的状态,若是是那种没有嵌套关系的组件,该如何来实现通讯呢?为了解决这个问题,Redux的方法就是将store放在根目录顶层组件中,一层层往下分发给各子组件,在子组件中进行调用,Redux的做用是让状态变得更加可预测、而且更容易管理。react
Redux由Flux框架演变而来,但在Flux的基础上Redux改变了整个框架中某些角色的做用,例如在Flux中你能够拥有多个store,每一个store存储本身对应的那部分状态,在Redux中,你只能维护一个store,存储了整个应用的全部状态,Redux更倾向于把store分发下去,dispatch action的时候,reducer根据状态对象的key值再将store进行拆分,reducer能拿到store中对应的那一部分进行处理,Redux提供createStore、combineReducers、applyMiddleware等一系列方法来配合React-redux使用帮咱们更好的对这个store进行管理,这里要详讲的是React-redux中的connect方法。git
想要把store绑定在视图层上,得用到React-redux中的两个主角:Provider和Connect,在api文档第一段话,做者说一般状况下你没法使用connect()去connect一个没有继承Provider的组件,也就是说若是你想在某个子组件中使用Redux维护的store数据,它必须是包裹在Provider中而且被connect过的组件,Provider的做用相似于提供一个大容器,将组件和Redux进行关联,在这个基础上,connect再进行store的传递。github
Provider组件源码:redux
export function createProvider(storeKey = 'store', subKey) { ...... class Provider extends Component { getChildContext() { return { [storeKey]: this[storeKey], [subscriptionKey]: null } } constructor(props, context) { super(props, context) this[storeKey] = props.store; } render() { return Children.only(this.props.children) } } }
从源码中能够看到,做者用了React的Context,Context解决了一个React中很常见的问题:当你的组件嵌套愈来愈深的时候,context能让你父组件和其它里层组件之间的通讯变的更方便,createProvider方法将返回一个Provider组件,该组件接受store和子组件,在Provider中定义了getChildContext方法来传递store,那么在子组件中利用contextTypes,你就能利用context访问到父级组件传递的store数据了。api
<Provider store>app
Props框架
store:应用中惟一的状态storeide
children: 应用的子组件
例子:
<Provider store={store}> <Router history={history}> <Route path="/" component={App}> <Route path="foo" component={Foo}/> <Route path="bar" component={Bar}/> </Route> </Router> </Provider>
来看下connect函数究竟是如何将store和组件联系在一块儿的,注意到api文档中有这样的一句话:
It does not modify the component class passed to it; instead, it returns a new, connected component class for you to use.
connenct并不会改变它“链接”的组件,而是提供一个通过包裹的connect组件。 conenct接受4个参数,分别是mapStateToProps,mapDispatchToProps,mergeProps,options(使用时注意参数位置顺序)。
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
mapStateToProps(state, ownProps) 方法容许咱们将store中的数据做为props绑定到组件中,只要store更新了就会调用mapStateToProps方法,mapStateToProps返回的结果必须是object对象,该对象中的值将会更新到组件中,例子:
const mapStateToProps = (state) => { return ({ count: state.counter.count }) }
mapDispatchToProps(dispatch, [ownProps]) 第二个参数容许咱们将action做为props绑定到组件中,mapDispatchToProps但愿你返回包含对应action的object对象,例如:
const mapDispatchToProps = (dispatch, ownProps) => { return { increase: (...args) => dispatch(actions.increase(...args)), decrease: (...args) => dispatch(actions.decrease(...args)) } } export default connect(mapStateToProps, mapDispatchToProps)(yourComponent)
当你想对组件的render更新进行更好的控制的时候,它也支持返回function方法,具体能够点击#279查看,例子:
const mapDispatchToProps = { // increment: () => increment(1), increase, // import increase function from action decrease }
mergeProps(stateProps, dispatchProps, ownProps) 该参数非必须,redux默认会帮你把更新维护一个新的props对象,相似调用Object.assign({}, ownProps, stateProps, dispatchProps)。
而options是为了更好的定制化设置的一个参数,容许返回5个boolean、function的值,我平时基本上没有接触到,想了解的能够参考api文档。
(本身平时写的一些总结,有误的地方欢迎交流指正)