网站开发技术可行性,郑州网站关键词优化,wordpress分类目录页面,百度爱采购推广怎么收费阅读react-redux源码 - 零阅读react-redux源码 - 一阅读react-redux源码(二) - createConnect、match函数的实现
上一节看了Provider组件的实现#xff0c;主要做的事情就是通过Context透传了来自redux的store和监听store变化的事件对象Subscription的实例。
本节会深入到co…阅读react-redux源码 - 零阅读react-redux源码 - 一阅读react-redux源码(二) - createConnect、match函数的实现
上一节看了Provider组件的实现主要做的事情就是通过Context透传了来自redux的store和监听store变化的事件对象Subscription的实例。
本节会深入到connect组件的内部查看实现方式整个connect组件的实现相对复杂并且巧妙。
通过入口文件可以知道connect组件是/src/connect/connect.js的默认导出。文件内容如下
import connectAdvanced from ../components/connectAdvanced
import shallowEqual from ../utils/shallowEqual
import defaultMapDispatchToPropsFactories from ./mapDispatchToProps
import defaultMapStateToPropsFactories from ./mapStateToProps
import defaultMergePropsFactories from ./mergeProps
import defaultSelectorFactory from ./selectorFactory/*connect is a facade over connectAdvanced. It turns its args into a compatibleselectorFactory, which has the signature:(dispatch, options) (nextState, nextOwnProps) nextFinalPropsconnect passes its args to connectAdvanced as options, which will in turn pass them toselectorFactory each time a Connect component instance is instantiated or hot reloaded.selectorFactory returns a final props selector from its mapStateToProps,mapStateToPropsFactories, mapDispatchToProps, mapDispatchToPropsFactories, mergeProps,mergePropsFactories, and pure args.The resulting final props selector is called by the Connect component instance wheneverit receives new props or store state.*/
function match(arg, factories, name) {for (let i factories.length - 1; i 0; i--) {const result factories[i](arg)if (result) return result}return (dispatch, options) {throw new Error(Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.)}
}function strictEqual(a, b) {return a b
}// createConnect with default args builds the official connect behavior. Calling it with
// different options opens up some testing and extensibility scenarios
export function createConnect({connectHOC connectAdvanced,mapStateToPropsFactories defaultMapStateToPropsFactories,mapDispatchToPropsFactories defaultMapDispatchToPropsFactories,mergePropsFactories defaultMergePropsFactories,selectorFactory defaultSelectorFactory
} {}) {return function connect(mapStateToProps,mapDispatchToProps,mergeProps,{pure true,areStatesEqual strictEqual,areOwnPropsEqual shallowEqual,areStatePropsEqual shallowEqual,areMergedPropsEqual shallowEqual,...extraOptions} {}) {const initMapStateToProps match(mapStateToProps,mapStateToPropsFactories,mapStateToProps)const initMapDispatchToProps match(mapDispatchToProps,mapDispatchToPropsFactories,mapDispatchToProps)const initMergeProps match(mergeProps, mergePropsFactories, mergeProps)return connectHOC(selectorFactory, { // used in error messagesmethodName: connect,// used to compute Connects displayName from the wrapped components displayName.getDisplayName: name Connect(${name}),// if mapStateToProps is falsy, the Connect component doesnt subscribe to store state changesshouldHandleStateChanges: Boolean(mapStateToProps),// passed through to selectorFactoryinitMapStateToProps,initMapDispatchToProps,initMergeProps,pure,areStatesEqual,areOwnPropsEqual,areStatePropsEqual,areMergedPropsEqual,// any extra options args can override defaults of connect or connectAdvanced...extraOptions})}
}export default /*#__PURE__*/ createConnect()
createConnect
首先看看createConnect关于函数如果有注释先看注释然后主要看函数名一个好的函数名会表明这个函数是做什么的。再看函数的入参和函数的出参最后可以看函数的实现方式。
export function createConnect({connectHOC connectAdvanced,mapStateToPropsFactories defaultMapStateToPropsFactories,mapDispatchToPropsFactories defaultMapDispatchToPropsFactories,mergePropsFactories defaultMergePropsFactories,selectorFactory defaultSelectorFactory
} {}) {return function connect(mapStateToProps,mapDispatchToProps,mergeProps,{pure true,areStatesEqual strictEqual,areOwnPropsEqual shallowEqual,areStatePropsEqual shallowEqual,areMergedPropsEqual shallowEqual,...extraOptions} {}) {}
}首先这个函数定义参数的形式有点奇怪function name({a 1, b 2} {})这种形式。这其实是JS中的命名参数的写法和Python、Dart之类的语言中提供的命名参数特性类似。入参的赋值和名字有关而不是位置。
而入参分别是connectHOC还有剩下来的几个factory分别是生产mapStateToProps的工厂、生产mapDispathToProps的工厂生产mergeProps的工厂和生产选择器的工厂。
后面createConnect函数会返回connect函数而这个connect函数就是连接组件用到的组件。
在底部会执行createConnect方法则会得到该方法返回的connect函数在组件中通过connect函数可以连接到顶层Provider提供的store和Subscribtion实例。
connect函数
return function connect(mapStateToProps,mapDispatchToProps,mergeProps,{pure true,areStatesEqual strictEqual,areOwnPropsEqual shallowEqual,areStatePropsEqual shallowEqual,areMergedPropsEqual shallowEqual,...extraOptions} {}) {const initMapStateToProps match(mapStateToProps,mapStateToPropsFactories,mapStateToProps)const initMapDispatchToProps match(mapDispatchToProps,mapDispatchToPropsFactories,mapDispatchToProps)const initMergeProps match(mergeProps, mergePropsFactories, mergeProps)return connectHOC(selectorFactory, {// used in error messagesmethodName: connect,// used to compute Connects displayName from the wrapped components displayName.getDisplayName: name Connect(${name}),// if mapStateToProps is falsy, the Connect component doesnt subscribe to store state changesshouldHandleStateChanges: Boolean(mapStateToProps),// passed through to selectorFactoryinitMapStateToProps,initMapDispatchToProps,initMergeProps,pure,areStatesEqual,areOwnPropsEqual,areStatePropsEqual,areMergedPropsEqual,// any extra options args can override defaults of connect or connectAdvanced...extraOptions})}connect函数就是我们用于连接store的函数。connect函数的入参分别是 mapStateToProps mapDispatchToPropsmergeProps和一个配置对象。
首先看下入参的配置对象
{pure true,areStatesEqual strictEqual,areOwnPropsEqual shallowEqual,areStatePropsEqual shallowEqual,areMergedPropsEqual shallowEqual,...extraOptions
} {}配置对象定义了用于对比数据的函数分别是对比store中的state对比被包裹组件自身的props对比被组件选中的store中的state对比被包裹组件自身的props和来自store的state被选中的state。
这里要注意我们知道一个连接到store的组件的props会有两个来源一个是store包括store中的state和dispatch。还有一个是父组件传递给组件的props。 而要做到性能最优则是接收到新的值时对这些值分别对比如果没有改变则不需要更新组件以优化组件性能。
const initMapStateToProps match(mapStateToProps,mapStateToPropsFactories,mapStateToProps
)
const initMapDispatchToProps match(mapDispatchToProps,mapDispatchToPropsFactories,mapDispatchToProps
)
const initMergeProps match(mergeProps, mergePropsFactories, mergeProps)这段代码统一处理了三个工厂函数生成目标函数的过程。
function match(arg, factories, name) {for (let i factories.length - 1; i 0; i--) {const result factories[i](arg)if (result) return result}return (dispatch, options) {throw new Error(Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.)}
}factories是数组遍历这个数组找到一个真的返回值返回出去否则返回一个会抛出错误的方法。这是责任链模式factories是一个链数组的每一项只处理自身的情况如果匹配则返回否则返回undefined通知match继续遍历链。
factories对应的数据结构式[() (fn || undefined), () (fn || undefined), ...]。
注意match从右往左遍历factories数组。
整理好相关入参全部传递给connectHOC这个高阶组件是整个connect的核心如何订阅store更新如何防止store的更新引起不必要的渲染如何处理ref的获取如何使用通过props传入的context和store如何透传父组件传入的props。这些都会在connect中处理。
阅读react-redux源码 - 零阅读react-redux源码 - 一阅读react-redux源码(二) - createConnect、match函数的实现