redux是一个js状态管理的库,由flux基础上开发出来,与flux的主要区别是只有一个store,关于store,后文会详述。在各大框架中都可使用,固然各个框架也有本身再度封装的状态管理库,如angular的ngrx,vue的vuex,而本文主要介绍的是react的react-redux。vue
本次演示的示例,是一个微信注册页面,主要想经过react-redux实现的功能是,当输入不合法的注册信息时,顶部出现错误提示信息,即:react
经过路由进入主页面,主页面渲染的dom代码为:git
render() { // 这个组件是一个包裹组件,全部的路由跳转的页面都会以this.props.children的形式加载到本组件下 const {msg} = this.props; return ( <div className="container"> <div ref="test" className="weui-toptips weui-toptips_warn" style={{'display': msg.show ? 'block' : 'none'}}>{msg.text}</div> <div className="page">{this.props.children}</div> </div> ); }
能够看到主页面比更没有直接写入注册页面,而由错误提示部分加子路由入口组成,注册页面是经过子路由嵌套进来的,而又由于react的数据没有向上回溯的能力(即单项数据流),所以这里选择状态管理的方式去显示错误提示信息。github
最初看文档的时候,有一种体验,就是各个模块(action,reducer,store)等等,都看明白了,可是具体想去完成功能的时候仍是一脸懵逼,不知道如何下手,因而此次为了去更好的讲解示例,我决定反着来,先从示例入手,再去引出那些概念。vuex
从以前主页面的代码能够看到,错误信息的显示是由组件的props传进来的,而主页面是如何获取相关的props的呢,答案是经过一个connect的函数。npm
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
connect是react组件作状态管理的核心,它将组件和redux中的全部状态值链接起来。这个函数接受四个参数,它们分别是 mapStateToProps,mapDispatchToProps,mergeProps和options。redux
第一个参数是获取redux仓库中的值的一个函数。为了方便快速理解,咱们能够简单粗暴的认为他是js中getter,setter中的getter,这是一个用来从redux中获取值的函数,这个函数返回的值,能够在当前组件的props中拿到。微信
好比如今主页面须要知道,当前redux仓库中是否显示错误提示的相关信息时,有以下代码:app
const mapStateToProps = (state) => { return { msg: state.tipMsg,//取reducer中的tipMsg } } export default connect(mapStateToProps)(Main);
state就是redux中储存值的大对象,而如今须要的错误信息就是存储在tipMsg的字段当中。由于在主页面只会取值,而不会设置值,所以connect只须要这一个函数足够。框架
ownProps这里还能够穿第二个参数,第二个参数特指当前组件的props,能够用来作信息对比。本例没有用到。
若是说mapStateToProps是一个getter的话,那么mapDispatchToProps就是一个setter,他触发了redux的相关行为,使得rudex能够保存记录一些你想要记录改变的状态和值。
具体到本例中,触发redux行为的操做在注册页面,所以注册页面添加以下代码:
const mapDispatchToProps = (dispatch) => { return bindActionCreators({ showTip: showTip//第二个showTip是一个action }, dispatch); } export default connect((state) => state, mapDispatchToProps)(Main);
能够看到当注册页面执行showTip的函数时,就会触发redux中的showTip的操做,这个操做是提早定义好的。这里有两个showTip,第一个是指当前页面的函数名,第二个是指redux中定义好的行为,这两个showTip没有必要的联系,只是做为一个关系映射,名字能够不同。
这个参数的做用是表示把redux中的props(即当中存储的值)和当前组件的props作合并,默认都是要合并的,能够忽略这个属性。
一个配置项属性,能够作相关的配置。自行翻译吧~。
[options] (Object) If specified, further customizes the behavior of the connector.
[pure = true] (Boolean): If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps, preventing unnecessary updates, assuming that the component is a “pure” component and does not rely on any input or state other than its props and the selected Redux store’s state. Defaults to true.
[withRef = false] (Boolean): If true, stores a ref to the wrapped component instance and makes it available via getWrappedInstance() method. Defaults to false.
这个就是以前一直提到的redux的仓库。redux的管理的数据都存储在store中。
咱们只须要知道,store就是一个存储仓库,react-redux只有一个store,全部的东西都存在这里,想要在react组件中用他首先须要去根页面把它注入进去。须要在根节点写入以下代码:
import React from 'react'; import {render} from 'react-dom'; // 渲染组件时须要 import {Provider} from 'react-redux'; // react和redux链接的桥梁,就是这个Provider import store from './redux/store/store'; // 引入sotre import route from './router/route'; // 全部定义好的路由 // 建立根组件 render( <Provider store={store}> {route} </Provider>, document.body.appendChild(document.createElement('div')) );
这是连接redux,使组件能够访问仓库的基础。
export const showTip = (item) => { return { type: 'SHOW_TIP', item } }
以前在注册页面,若是没有知足相关条件,则触发redux的行为。而这个行为就是action。action具体定义了项目中触发的行为类别,经过type属性来区别于不一样的行为。对应到connect的函数参数中,就是mapDispatchToProps须要去save或者说change什么样的行为。
const tipMsg = (state = {text: '', show: false}, action) => { switch (action.type) { case 'SHOW_TIP': return Object.assign({}, { text: action.item.text, show: action.item.show }); default: return state; } }
一个纯函数,经过判断是什么样的行为,来对相关的state作更改,这中间是不含任何变量的,即只要肯定输入,就能知道输出。在mapStateToProps这个取值函数中,取的也就是相关reducer中返回的值。
触发相关action后的主页控制台:
至此,就完成了react-redux对于父子组件的通讯,由子组件向上推送信息至父组件,触发相关的操做。
项目地址:https://github.com/jiwenjiang...(ps:注意此项目由yarn管理,而不是npm)