React-Redux主要由两部分组成,一是Provider(提供者),顾名思义作用就是提供状态数据。

另一部分是connect函数,它的作用是把UI组件和状态数据“连接”起来,实现了Model和View的分离,也就是UI组件并不直接管理状态数据,而是只负责界面的展示。

通过connect函数可以获得一个容器组件的创建器,进而创建出容器组件,而容器组件又包含了UI组件,由于容器组件是可以获取到状态数据的,获取到之后再传给UI组件就可以实现UI组件和状态数据的连接。

下面我们先来实现第一部分——Provider。

React-Redux库作用相当于是简化React对Redux的操作(因为Redux是独立于React的库,甚至也可以配合Vue.js等使用),因此React-Redux中的Provider并不直接拥有状态数据,

状态数据是在Redux中的。即Provider需要接收Redux中状态数据所在的store模块,才能获取到状态数据。如下:

<Provider store={store}>
<App/>
</Provider>

我们刚才说了容器组件需要获取状态数据,而Provider是状态数据的提供者,因此Provider需要将状态数据传给容器组件。Provider的实现非常简单,如下。

export class Provider extends React.Component {

  static propTypes = {
store: PropTypes.object.isRequired // 声明接收Redux的store模块
}  // 声明要传给子组件(即容器组件)的数据名称(key)和数据类型
static childContextTypes = {
store: PropTypes.object
}  /* 指定上面的key对应的value */
getChildContext () {
return {
store: this.props.store
}
} render() {
  // 渲染<Provider>的所有子组件,在本例中就是<App/> return this.props.children
}
}

接下来实现connect函数,我们刚才说了connect会产生一个包装了UI组件的容器组件的创建器。而UI组件一方面负责界面的显示(读取状态数据),另一方面又要和用户交互,如监听按钮的点击事件,并执行某些操作(修改状态数据)。

因此UI组件需要拥有两类属性,一类我们叫做stateProps,即状态数据,UI组件会将状态数据渲染到界面上。另一类叫dispatchProps(即更新状态数据的方法),dispatch是redux中的概念,可以通过dispatch函数分发一个action(执行某个动作,进而修改状态数据)。

UI组件可以调用dispatchProps中的方法去间接地修改状态数据。

由于容器组件接收的是store,而store包含的是Redux全量的状态数据,而某个UI组件可能只需要整个应用中部分的状态数据,因此需要一个名为mapStateToProps的函数指定该UI组件需要哪些状态数据。

例如mapStateToProps=state=>({user:state.user}),这个函数就表明了该UI组件只需要状态数据中的user。

同理,在Redux中有actions的概念,它包含了所有的操作类型,而某个UI组件可能也只需要做一部分操作,因此需要一个名为mapDispatchToProps的对象指定该UI组件需要哪些操作类型。

mapDispatchToProps一般是如下格式(①)

格式①:
{
key1: actionCreator1,
key2: actionCreator2
}

其中key是操作的名称,而后面的actionCreator是一个action的创建器,可以调用创建器产生action,进而通过dispatch方法分发该action。

我们最终要想获得dispatchProps,需要将其转换成如下这样的格式(②)。因为action的内容可能是变化的,比如我们要更新状态数据里面的user,需要产生一个对应的例如"updateUser"这样的action,显然我们在action中需要携带用户信息,不然怎么更新呢。因此

actionCreator是可以接收参数的,根据参数创建一个action。


格式②:
{
key1:(...arguments)=>{ dispatch(actionCreator1(...arguments)) }, key2:(...arguments)=>{ dispatch(actionCreator2(...arguments)) }
}

好了,准备知识都已经介绍完了,下面可以开始编写connect函数啦。

export function connect(mapStateToProps, mapDispatchToProps) {
// 接收两个参数,根据参数构造出UI组件所需的stateProps(状态数据)和dispatchProps(更新状态数据的方法)
//connect函数的返回值是一个ContainerComponentCreator,也就是容器组件的创建器,而我们说过容器组件会包装一个UI组件,因此创建器的方法参数是一个UI组件
return (UIComponent) => {
return class ContainerComponent extends React.Component { // 容器组件需要声明接收Provider提供的store
static contextTypes = {
store: PropTypes.object
} constructor (props, context) {
super(props)//调用父类构造器,不解释      // 得到Provider传过来的store
const store = context.store
// 构造状态数据
const stateProps = mapStateToProps(store.getState())
// 将状态数据作为容器的state(因为状态改变意味着我们的UI组件需要随之变化,而state的改变正好会使得容器组件重新渲染)
this.state = {...stateProps} //构造dispatchProps(更新状态数据的方法),这段不解释,请对照上面的格式①和格式②,很容易看出这段代码做了什么
const dispatchProps = Object.keys(mapDispatchToProps).reduce((pre, key) => {
const actionCreator = mapDispatchToProps[key]
pre[key] = (...args) => store.dispatch(actionCreator(...args))
return pre
}, {}) // 保存到组件上
this.dispatchProps = dispatchProps
// 绑定redux状态变化的监听
store.subscribe(() => { // 状态变化的回调
// 更新容器组件的状态,使容器组件重新渲染,进而导致UI组件的更新
this.setState({...mapStateToProps(store.getState())})
})
} render () {
// 渲染UI组件,并把UI组件所需的stateProps(状态数据)和dispatchProps(更新状态数据的方法)传入
return <UIComponent {...this.state} {...this.dispatchProps}/>
}
} }
}

最新文章

  1. 如何在select下拉列表中添加复选框?
  2. shell return value
  3. 在CentOS上搭建svn服务器及注意事项
  4. ABAP 内表的行列转换-发货通知单-打印到Excel里-NEW-(以运单号为单位显示ALV然后保存输出)
  5. ACM训练计划建议(写给本校acmer,欢迎围观和指正)
  6. mssql 获取表空间大小
  7. app之间的互相跳转
  8. 百度快收录吧!!!a39fe054b88866bc737dd5fb02f39e41
  9. 大型项目 Gradle 的常用库和版本管理[转]
  10. UVa 11825 集合dp
  11. JSON的parse()方法
  12. iOS UIScrollView偏移量属性
  13. GitHub的实现是否是基于此语言的支持网络编程性呢?
  14. Microsoft SQL - 学习总目录
  15. 步步为营-104-SQL语句(截取字符串)
  16. 在WINDOWS7下无U盘安装WINDOWS10
  17. matplotlib极坐标方法详解
  18. vue-cli之webpack的proxyTable无效的解决方案
  19. 安装虚拟环境virtualenvwrapper和django
  20. 平面最近点对模板[luogu P1429]

热门文章

  1. 引发了未经处理的异常:读取访问权限冲突。 _First 是 nullptr。
  2. 【零基础】快速入门爬虫框架HtmlUnit
  3. decimal模块 --数字的精度、保留小数位数、取整问题
  4. react 实现数据双向绑定
  5. 中间件 | Nginx实现动静分离
  6. Going Deeper with Convolutions阅读摘要
  7. Node安装配置
  8. [CDH] New project for ML pipeline
  9. 由DBCursor的“can&#39;t switch cursor access methods”异常引发的思考
  10. jenkins配置jdk、git、maven