react使用redux作状态管理,实现多个组件之间的信息共享,解决了父子组件、兄弟组件之间的复杂通讯问题。vue有vuex,总之是一种flux的思想。react提供了react-redux这个库,一看名字就知道是为了将react和redux关联起来,react-redux有connect高阶函数以及Provider组件、milddleware、thunk等,来实现一下。vue
篇幅过长,多分了几篇。react
这里先不考虑中间件机制vuex
import { createStore } from 'redux' function counter(state = 10, action) { console.log(state, action) switch (action.type) { case 'add': return state + 1 case 'less': return state - 1 default: return state } } const store = createStore(counter) const init = store.getState() console.log(`Init count: ${init}`) function listener(){ const current = store.getState() console.log(`count: ${current}`) } store.subscribe(listener) store.dispatch({ type: 'add' }) store.dispatch({ type: 'less' })
这是redux简单的例子,首先咱们定义了一个reducer叫作counter,接下来使用redux提供的createStore方法将reducer传入,构造出了一个store,而后基于观察者模式,触发相应的action,进行相应的响应。redux
Redux重点的方法就是createStore、getState、subscribe、dispatch这四个方法。大致讲一下思路,咱们的Redux,这里就叫myRedux,myRedux和Redux同样,都是只暴露出来一个方法,那就是createStore,而后createStore保存着一个state,能够是对象、字符串、数组等,能够经过getState方法来访问state,还有对state的监听器以及订阅的方法,实现一下。数组
export function createStore (reducer) { let state = {} let listeners = [] function getState () { return state } function subscribe (listener) { listeners.push(listener) } function dispatch (action) { state = reducer(state, action) listeners.forEach(listener => listener()) return action } // 为了确保createStore以后,store.getState中就有state的初始值 dispatch({type: '@myRedux/qwe'}) return {getState, subscribe, dispatch} }
其实就是一个观察者模式,值得注意的是:当执行完createStore以后,执行stroe.getState方法就能获取到初始的状态(咱们这里是10),因此须要咱们的reducer先执行一次,那么咱们就要在createStore中就先dispatch一下,代码中有体现。Redux中也是这么作的,Redux初始化dispatch的type值是@@redux/INIT
,能够看一下。安全
这么作是为了确保初始化dispatch的type值不会和用户定义的type值重复,咱们代码里type为@myRedux/qwe
。less
要理解react-redux原理,必须先说下react中的context。父组件向子组件传递数据,能够经过props,若是层级比较深呢?就很差了,会有性能问题,咱们能够经过context来实现跨级传递数据。ide
context是全局的,在组件中声明,全部的子组件均可以获取到context,react以为全局不是很安全,因此要求context都是强数据类型,即任何想访问context里面的属性的组件都必须指定一个contextTypes
的属性,若是没有指定该属性的话,用this.context
访该属性就会出错。函数
一样,经过getChildContext
方法指定传递给子组件的属性也须要被指定数据类型,经过childContextTypes来指定,不指定一样会产生错误。性能
下面是一个简单例子。
import React from 'react' import PropTypes from 'prop-types' class Son extends React.Component{ render(){ return ( <div> <p>子组件</p> <GrandSon/> </div> ) } } class GrandSon extends React.Component{ static contextTypes = { user:PropTypes.string } render(){ console.log(this.context) return ( <div> <p>孙组件</p> <div>孙组件收到来自父组件的信息:{this.context.user}</div> </div> ) } } class Father extends React.Component{ static childContextTypes = { user:PropTypes.string } constructor(props){ super(props) this.state = {user:'user12'} } getChildContext(){ return this.state } render(){ return ( <div> <p>父组件,要给孙组件:{this.state.user}</p> <Son/> </div> ) } } export default Father
在这里就不须要经过props一层一层的往下传递属性了,这就是context。
那么context和咱们的react-redux有什么关系呢,用过的都知道,Provider组件在整个应用组件上包了一层,让整个应用组件成为Provider的子组件,看到这里,你是否是有点懂了,跟上面的例子很像嘛,对的,就是这样,咱们的Provider组件接收Redux的store做为props,经过context对象传递给子组件。
咱们下一篇就会说道Provider组件。