注:这篇文章只是讲解React Redux这一层,并不包含Redux部分。Redux有计划去学习,等之后学习了Redux源码之后再作分析
注:代码基于如今(2016.12.29)React Redux的最新版本(5.0.1)segmentfault
这里有四个参数:工具
mapStateToProps, mapDispatchToProps, mergeProps都是通过mapDispatchToProps, mapStateToProps, mergeProps封装过的学习
displayName是option里面传入的
主要作的是检查传入的mapStateToProps,mapDispatchToProps,mergeProps是否存在,因为这里的对象是通过几个map方法封装过的,因此不存在就说明开发传入的值是错误的。同时检查是否有dependsOnOwnProps这个属性,若是没有给一个warning.spa
import warning from '../utils/warning' function verify(selector, methodName, displayName) { if (!selector) { throw new Error(`Unexpected value for ${methodName} in ${displayName}.`) } else if (methodName === 'mapStateToProps' || methodName === 'mapDispatchToProps') { //只检查mapStateToProps和mapDispatchToProps, 由于mergeProps方法不须要 if (!selector.hasOwnProperty('dependsOnOwnProps')) { warning( `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.` ) } } } export default function verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, displayName) { verify(mapStateToProps, 'mapStateToProps', displayName) verify(mapDispatchToProps, 'mapDispatchToProps', displayName) verify(mergeProps, 'mergeProps', displayName) }
这里主要负责获取处理过的mapStateToProps, mapDispatchToProps, mergeProps和传入的options,来进行props的合并,最后返回合并后的结果。其中,当pure为true的时候,会对props进行存储,便于下一次比较,若是经过比较两个相同,那么就不改变props对象,减小没必要要的re-render。code
在connectAdvanced.js里面看到这么一段注释:对象
selectoryFactory方法返回的是一个function,这个function的做用是根据Redux Store state, props和dispatch计算新的props. 在connectAdvanced中会提供dispatch给selectorFactory,以便selectorFactory能够对actionCreator进行绑定。connectAdvanced获取的option配置会直接被传给selectorFactory,其中就包含了displayName和wrappedComponent(其实还有一些对比的方法在里面)。ci
selectorFactory负责记录全部的状态(props, store state, dispatch, mergedProps),以便在部分状态发生改变,而不影响组件渲染的时候,能够避免没必要要的渲染。开发
export default function finalPropsSelectorFactory(dispatch, { initMapStateToProps, initMapDispatchToProps, initMergeProps, ...options }) { const mapStateToProps = initMapStateToProps(dispatch, options) const mapDispatchToProps = initMapDispatchToProps(dispatch, options) const mergeProps = initMergeProps(dispatch, options) if (process.env.NODE_ENV !== 'production') { verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, options.displayName) } const selectorFactory = options.pure ? pureFinalPropsSelectorFactory : impureFinalPropsSelectorFactory return selectorFactory( mapStateToProps, mapDispatchToProps, mergeProps, dispatch, options ) }
这里只是给mapStateToProps, mapDispatchToProps, mergeProps传入dispatch和options对象,而后根据pure的值传给不一样的方法进行处理。get
若是pure是true, 那么selectorFactory返回的selector会负责存储最后结果。若是结果没有发生改变,那么connectAdvanced的shouldComponentUpdate就会返回false。
若是pure是false, 那么selector永远会返回一个新的对象,同时shouldComponentUpdate永远都返回true
这个factory方法会返回一个function,接收Redux Store和ownProps做为参数。做用是,每次store或ownProps发生改变之后,调用这个返回的function,获取更新后的最终props。
export function impureFinalPropsSelectorFactory( mapStateToProps, mapDispatchToProps, mergeProps, dispatch ) { return function impureFinalPropsSelector(state, ownProps) { return mergeProps( mapStateToProps(state, ownProps), mapDispatchToProps(dispatch, ownProps), ownProps ) } }
根据pure等于false的状况,这里会永远返回一个新的对象。存粹的、不加任何判断的调用mergeProps对几个props的结构进行合并。
这里返回的值的格式是:(state, ownProps)=>final props
。
export function pureFinalPropsSelectorFactory( mapStateToProps, mapDispatchToProps, mergeProps, dispatch, { areStatesEqual, areOwnPropsEqual, areStatePropsEqual } ) { let hasRunAtLeastOnce = false // 是不是第一次调用,第一次调用不须要作是否改变的检查 let state // 记忆上一次的state let ownProps // 记忆上一次的ownProps let stateProps // 记忆mapStateToProps返回的props let dispatchProps // 记忆mapDispatchToProps返回的props let mergedProps // 记忆最后合并后的结果 // 第一次调用的时候,纯粹记住全部的结果 function handleFirstCall(firstState, firstOwnProps) { state = firstState ownProps = firstOwnProps stateProps = mapStateToProps(state, ownProps) dispatchProps = mapDispatchToProps(dispatch, ownProps) mergedProps = mergeProps(stateProps, dispatchProps, ownProps) hasRunAtLeastOnce = true return mergedProps } // 当两个都发生改变。。。 function handleNewPropsAndNewState() { stateProps = mapStateToProps(state, ownProps) // ownProps发生了改变,确定须要调用获取新的props if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps) mergedProps = mergeProps(stateProps, dispatchProps, ownProps) return mergedProps } // 若是只有父组件传入的props发生了改变,那么须要根据dependsOnOwnProps来进行更新 function handleNewProps() { if (mapStateToProps.dependsOnOwnProps) stateProps = mapStateToProps(state, ownProps) if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps) // 因为ownProps发生了改变,因此不须要进行检查,直接调用mergeProps方法 mergedProps = mergeProps(stateProps, dispatchProps, ownProps) return mergedProps } // 若是只有Redux store state发生了改变,那么只用更新mapStateToProps的返回值,由于dispatchProps和Redux State无关 function handleNewState() { const nextStateProps = mapStateToProps(state, ownProps) const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps) stateProps = nextStateProps if (statePropsChanged) mergedProps = mergeProps(stateProps, dispatchProps, ownProps) return mergedProps } // 除第一次调用外,每次都须要对各类结果进行检查,而后记录必要的结果 function handleSubsequentCalls(nextState, nextOwnProps) { const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps) // 检查ownProps是否发生改变 const stateChanged = !areStatesEqual(nextState, state) // 检查Redux store state是否发生改变 state = nextState ownProps = nextOwnProps // 根据改变的不一样,调用不一样的方法。减小没必要要的运算 if (propsChanged && stateChanged) return handleNewPropsAndNewState() if (propsChanged) return handleNewProps() if (stateChanged) return handleNewState() return mergedProps } return function pureFinalPropsSelector(nextState, nextOwnProps) { return hasRunAtLeastOnce ? handleSubsequentCalls(nextState, nextOwnProps) : handleFirstCall(nextState, nextOwnProps) } }
当pure等于true的时候,须要作出各类检查来断定是否须要调用方法,来获取新的props.
当Redux state发生改变,ownProps没变的时候
1) 因为mapDispatchToProps并无基于Redux State,因此dispatchProps是须要进行更新的。2) 而mapStateToProps是基于Redux State的,因此须要调用mapStateToProps方法或许"新的"stateProps。因为State发生改变,并不必定会形成返回结果的改变,因此须要根据检查后的结果来断定是否调用mergeProps方法。
当OwnProps发生改变,Redux State没有改变的时候
1) 因为mapDispatchToProps和mapStateToProps均可能基于ownProps,因此须要根据dependsOnOwnProps属性来检查,判断是否须要调用方法进行更新。2) ownProps做为mergeProps的一个必要参数,因此不须要作任何判断,mergePorps必须被调用
当Redux Store, OwnProps都发生了改变
综合以前的两点,mapStateToProps必须调用,mapDispatchToProps根据dependsOnOwnProps属性调用,mergeProps必须调用
在connect定义的时候,通常尽可能使用pure:true的状况(默认值),由于在这种状况下,会对props进行差异检查。若是没有改变,就不会去调用connectAdvanced组件去更新。若是内部组件同时根据 除 父组件传入的props和Redux store的其余状态进行更新渲染,那么pure必须是false。
option中的areStatesEqual(默认值为===),areOwnPropsEqual(默认值为shallowEqual), areStatePropsEqual(默认值为shallowEqual), areMergedPropsEqual(默认值为shallowEqual),能够根据须要来修改这几个参数,当pure为true的时候,检查更多没必要要的re-render