react-redux源码

前端之家收集整理的这篇文章主要介绍了react-redux源码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

index.js

  1. import Provider from './components/Provider'
  2. import connectAdvanced from './components/connectAdvanced'
  3. import connect from './connect/connect'
  4.  
  5. export { Provider,connectAdvanced,connect }

Provide.js

  1. import { Component,PropTypes,Children } from 'react'
  2. // 传入Subscription的意义及用法???
  3. import Subscription from '../utils/Subscription'
  4. import storeShape from '../utils/storeShape'
  5. import warning from '../utils/warning'
  6.  
  7. // 开发环境下,组件更新时store变更,打印错误
  8. let didWarnAboutReceivingStore = false
  9. function warnAboutReceivingStore() {
  10. if (didWarnAboutReceivingStore) {
  11. return
  12. }
  13. didWarnAboutReceivingStore = true
  14.  
  15. warning(
  16. '<Provider> does not support changing `store` on the fly. ' +
  17. 'It is most likely that you see this error because you updated to ' +
  18. 'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' +
  19. 'automatically. See https://github.com/reactjs/react-redux/releases/' +
  20. 'tag/v2.0.0 for the migration instructions.'
  21. )
  22. }
  23.  
  24. // Provider作为容器组件,向子组件上下文对象context注入props.store,即Redux的store
  25. export default class Provider extends Component {
  26. getChildContext() {
  27. return { store: this.store,storeSubscription: null }
  28. }
  29.  
  30. constructor(props,context) {
  31. super(props,context)
  32. this.store = props.store
  33. }
  34.  
  35. render() {
  36. return Children.only(this.props.children)
  37. }
  38. }
  39.  
  40. if (process.env.NODE_ENV !== 'production') {
  41. Provider.prototype.componentWillReceiveProps = function (nextProps) {
  42. const { store } = this
  43. const { store: nextStore } = nextProps
  44.  
  45. if (store !== nextStore) {
  46. warnAboutReceivingStore()
  47. }
  48. }
  49. }
  50.  
  51. Provider.propTypes = {
  52. store: storeShape.isrequired,children: PropTypes.element.isrequired
  53. }
  54. Provider.childContextTypes = {
  55. store: storeShape.isrequired,storeSubscription: PropTypes.instanceOf(Subscription)
  56. }
  57. Provider.displayName = 'Provider'

connect.js

  1. // connectAdvanced函数由connect模块内部调用,铰链redux.store和react组件
  2. // 目的是通过react.props获取redux.state、redux.dispatch(action)的相关特征,传输数据流和派发事件
  3. // 同时获得redux.dispatch特征的props.actionname派发事件时,触发react.props重新计算和组件视图重绘
  4. // 返回函数接受react组件构造函数为参数,用以形成高阶组件,作为视图层render方法渲染的参数
  5. import connectAdvanced from '../components/connectAdvanced'
  6.  
  7. // 比较变量是否全等,或者普通对象单层比较是否相同
  8. import shallowEqual from '../utils/shallowEqual'
  9.  
  10. // 当用户配置的mapDispatchToProps是函数时,使用wrapMapToPropsFunc装饰mapDispatchToProps
  11. // 传入redux的dispatch方法、react组件的displayName
  12. // 当用户配置的mapDispatchToProps不是函数时,设置默认的mapDispatchToProps为输出redux.store.dispatch方法;否则不设置
  13. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  14. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性
  15. import defaultMapDispatchToPropsFactories from './mapDispatchToProps'
  16.  
  17. // 当用户配置的mapStateToProps是函数时,使用wrapMapToPropsFunc装饰mapStateToProps
  18. // 传入redux的dispatch方法、react组件的displayName
  19. // 当用户配置的mapStateToProps不是函数时,设置默认的mergeProps为空函数;否则不设置
  20. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  21. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性Props为空函数;否则不设置
  22. import defaultMapStateToPropsFactories from './mapStateToProps'
  23.  
  24. // 当用户配置的mergeProps是函数时,使用wrapMergePropsFunc装饰mergeProps
  25. // 传入redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual
  26. // 当用户配置的mergeProps不是函数时,设置默认的mergeProps为defaultMergeProps
  27. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  28. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性Props为空函数;否则不设置
  29. import defaultMergePropsFactories from './mergeProps'
  30.  
  31. // 传入connectAdvanced模块
  32. // 函数,以redux.store.dispatch、react.options为参数,返回react.props计算函数
  33. import defaultSelectorFactory from './selectorFactory'
  34.  
  35. // factories为数组形式的函数队列,用于装饰用户配置的mapStateToProps、mapDispatchToProps、mergeProps(作为参数)
  36. // 根据参数为空、为函数、为对象,按条件构造装饰函数构造器
  37. // 该构造器接受相应redux的dispatch方法及react组件的options属性方法
  38. // 并传入mapStateToProps、mapDispatchToProps、mergeProps函数中,或redux方法改造mapDispatchToProps函数
  39. // 完成装饰,最终结果是赋予react组件的props,以redux.store.state,redux.store.dispatch的方法属性
  40. // 针对react组件更新重绘的情形,这一过程由挂载在react组件props上的redux.store.dispatch引起
  41. // 通过挂载在react组件上的this.selector.run重新计算props,获取redux.store.state,redux.store.dispatch
  42. // this.selector.run在react组件上挂载this.subscription实例的onStateChange方法调用
  43. // 而本层组件的onStateChange方法通过redux.store.subscribe绑定为回调函数
  44. // 同时本层组件的onStateChange触发this.subscription.notifyNestedSubs方法
  45. // 而子组件的onStateChange通过this.subscription.addNestedSub绑定为回调函数
  46. // 这样redux.store.dispatch就可以触发父子组件的props更新
  47. // 最终调用react组件的setState方法重绘组件
  48. function match(arg,factories,name) {
  49. for (let i = factories.length - 1; i >= 0; i--) {
  50. const result = factories[i](arg)
  51. if (result) return result
  52. }
  53.  
  54. return (dispatch,options) => {
  55. throw new Error(`Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.`)
  56. }
  57. }
  58.  
  59. // 判断是否完全相等
  60. function strictEqual(a,b) { return a === b }
  61.  
  62. // createConnect函数通常为内部调用,各参数均为默认值;这样处理的好处是便于模块化,在各模块中设置默认值
  63. export function createConnect({
  64. connectHOC = connectAdvanced,mapStateToPropsFactories = defaultMapStateToPropsFactories,mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,mergePropsFactories = defaultMergePropsFactories,selectorFactory = defaultSelectorFactory
  65. } = {}) {
  66.  
  67. // connect函数作为外部api接口,各参数均由用户传入;返回函数,接受待包装的react组件作为参数
  68. // 通过内部调用connectHOC(selectorFactory,options)(basicComponent)构造基于react组件的高阶组件basicComponent
  69. // 该组件赋予selector属性,其中selector.run方法用于重新计算props
  70. // 计算props的过程,需要通过传入当前redux.store的dispatch方法、高阶组件属性options
  71. // 借此装饰用户配置mapStateToProps、mapDispatchToProps、mergeProps函数,mapDispatchToProps可以是对象
  72. // 该组件赋予subscription属性,通过subscription.onStateChange作为redux.store.dispatch的直接或间接回调函数
  73. // 而subscription.onStateChange内部调用react.selector.run重新计算样式值、react.setState重绘组件
  74. // 注:用户配置的mapStateToProps、mapDispatchToProps为函数,可添加dependsOnOwnProps属性
  75. // 当其为真值时,意味通过redux的state、dispatch更新react组件的props时,需要原有的props作为参数
  76.  
  77. // mapStateToProps将redux.store.state映射给props,store.state变动引起props相应变动
  78. // 示例:redux.store.state改变,将引起props.todos属性作相应改变
  79. // const mapStateToProps = (state) => {
  80. // return {
  81. // todos: getVisibleTodos(state.todos,state.visibilityFilter)
  82. // }
  83. // }
  84. // const getVisibleTodos = (todos,filter) => {
  85. // switch (filter) {
  86. // case 'SHOW_ALL':
  87. // return todos
  88. // case 'SHOW_COMPLETED':
  89. // return todos.filter(t => t.completed)
  90. // case 'SHOW_ACTIVE':
  91. // return todos.filter(t => !t.completed)
  92. // default:
  93. // throw new Error('Unknown filter: ' + filter)
  94. // }
  95. // }
  96.  
  97. // mapDispatchToProps将redux.store.dispatch映射给props,便于通过props[actionname]调用redux.store.dispatch方法
  98. // 示例1:可通过props.onClick()触发redux事件机制,即通过dispatch派发action
  99. // dispatch方法由装饰函数传入
  100. // mapDispatchToProps为函数形式,待装饰,才可以传入dispatch方法
  101. // const mapDispatchToProps = (
  102. // dispatch,// ownProps
  103. // ) => {
  104. // return {
  105. // onClick: () => {
  106. // dispatch({
  107. // type: 'SET_VISIBILITY_FILTER',// filter: ownProps.filter
  108. // });
  109. // }
  110. // };
  111. // }
  112. // 示例2:props.onClick()将通过react-redux内部机制自动调用dispatch派发action,action由mapDispatchToProps构造
  113. // 装饰过程中调用redux的bindActionCreators生成用于派发相应action的方法,内部调用dispatch方法
  114. // mapDispatchToProps为对象形式,才可以调用redux的bindActionCreators方法
  115. // const mapDispatchToProps = {
  116. // onClick: (filter) => {
  117. // type: 'SET_VISIBILITY_FILTER',// filter: filter
  118. // };
  119. // }
  120. return function connect(
  121. mapStateToProps,mapDispatchToProps,mergeProps,// 可重写的属性包括areStatesEqual、areOwnPropsEqual、areStatePropsEqual、areMergedPropsEqual
  122. // 以及methodName(错误提示用)、等
  123. {
  124. // 真值时,redux.dispatch派发action事件触发时,将优化react.props计算方案
  125. // 否值时,傻瓜式重新计算react.props
  126. pure = true,// 默认判断redux.state是否修改,需要重新将redux.state、redux.dispatch按条件赋值给react.props
  127. // 用户重写判断机制,可以实现修改redux.state部分属性时,避过react-redux通过redux.store重新计算props
  128. areStatesEqual = strictEqual,// 默认判断react.props是否修改,需要重新,需要重新将redux.state、redux.dispatch按条件赋值给react.props
  129. // 用户重写判断机制,可以实现修改react.props部分属性时,避过react-redux通过redux.store重新计算props
  130. areOwnPropsEqual = shallowEqual,// 由mapStateToProps函数获得的stateProps是否与前一次相同,可避免react.props的重新赋值
  131. areStatePropsEqual = shallowEqual,// 由redux.state、redux.dispatch混合构造的mergeProps是否与前一次相同,可避免react.props的重新赋值
  132. areMergedPropsEqual = shallowEqual,...extraOptions
  133. } = {}
  134. ) {
  135.  
  136. // 当用户配置的mapStateToProps是函数时,使用wrapMapToPropsFunc装饰mapStateToProps
  137. // 传入redux的dispatch方法、react组件的displayName
  138. // 当用户配置的mapStateToProps不是函数时,设置默认的mergeProps为空函数;否则不设置
  139. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  140. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性Props为空函数;否则不设置
  141. const initMapStateToProps = match(mapStateToProps,mapStateToPropsFactories,'mapStateToProps')
  142. // 当用户配置的mapDispatchToProps是函数时,使用wrapMapToPropsFunc装饰mapDispatchToProps
  143. // 传入redux的dispatch方法、react组件的displayName
  144. // 当用户配置的mapDispatchToProps不是函数时,设置默认的mapDispatchToProps为输出redux.store.dispatch方法;否则不设置
  145. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  146. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性
  147. const initMapDispatchToProps = match(mapDispatchToProps,mapDispatchToPropsFactories,'mapDispatchToProps')
  148. // 当用户配置的mergeProps是函数时,使用wrapMergePropsFunc装饰mergeProps
  149. // 传入redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual
  150. // 当用户配置的mergeProps不是函数时,设置默认的mergeProps为defaultMergeProps
  151. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  152. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性Props为空函数;否则不设置
  153. const initMergeProps = match(mergeProps,mergePropsFactories,'mergeProps')
  154.  
  155. return connectHOC(selectorFactory,{
  156. methodName: 'connect',// 用于错误提示
  157.  
  158. // used to compute Connect's displayName from the wrapped component's displayName.
  159. getDisplayName: name => `Connect(${name})`,// react.store.dispatch(外部接口为react.props.actionname)触发改变props,是否重绘组件
  160. shouldHandleStateChanges: Boolean(mapStateToProps),initMapStateToProps,initMapDispatchToProps,initMergeProps,pure,areStatesEqual,areOwnPropsEqual,areStatePropsEqual,areMergedPropsEqual,...extraOptions
  161. })
  162. }
  163.  
  164. }
  165.  
  166. export default createConnect()

connectAdvanced.js

  1. import hoistStatics from 'hoist-non-react-statics'
  2. import invariant from 'invariant'
  3. import { Component,createElement } from 'react'
  4.  
  5. // 通过向react组件挂载this.subscription对象
  6. // 将当前组件及其子孙组件的subscription.onStateChange绑定为redux.stroe.dispatch方法的回调
  7. // subscription.onStateChange方法中,调用this.selector.run重新计算props
  8. // 本层组件的onStateChange方法通过redux.store.subscribe绑定为回调函数
  9. // 同时本层组件的onStateChange触发this.subscription.notifyNestedSubs方法
  10. // 而子组件的onStateChange通过this.subscription.addNestedSub绑定为回调函数
  11. // 这样redux.store.dispatch就可以触发父子组件的props更新
  12. import Subscription from '../utils/Subscription'
  13.  
  14. import storeShape from '../utils/storeShape'
  15.  
  16. let hotReloadingVersion = 0
  17.  
  18. // connectAdvanced函数由connect模块内部调用,铰链redux.store和react组件
  19. // 目的是通过react.props获取redux.state、redux.dispatch(action)的相关特征,传输数据流和派发事件
  20. // 同时获得redux.dispatch特征的props.actionname派发事件时,触发react.props重新计算和组件视图重绘
  21. // 返回函数接受react组件构造函数为参数,用以形成高阶组件,作为视图层render方法渲染的参数
  22.  
  23. // 首参selectorFactory默认为selectorFactory模块
  24. // 用于定义最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps的执行机制
  25. // 通过redux、react相关树形,构造react.props计算函数
  26. // 次参options对象,相关配置
  27. export default function connectAdvanced(
  28. selectorFactory,{
  29. // the func used to compute this HOC's displayName from the wrapped component's displayName.
  30. // probably overridden by wrapper functions such as connect()
  31. getDisplayName = name => `ConnectAdvanced(${name})`,// 错误提示
  32. methodName = 'connectAdvanced',// if defined,the name of the property passed to the wrapped element indicating the number of
  33. // calls to render. useful for watching in react devtools for unnecessary re-renders.
  34. renderCountProp = undefined,// redux.store.state初始化赋值、redux.store.dispatch方法触发时引起store.state变更,是否影响组件的props
  35. // 默认影响,shouldHandleStateChanges置为false时不影响,即redux监听state变更不影响react视图渲染
  36. // 用户使用react-redux,shouldHandleStateChanges由用户配置的mapStateToProps是否为真值决定
  37. shouldHandleStateChanges = true,// the key of props/context to get the store
  38. storeKey = 'store',// if true,the wrapped element is exposed by this HOC via the getWrappedInstance() function.
  39. withRef = false,// additional options are passed through to the selectorFactory
  40. ...connectOptions
  41. } = {}
  42. ) {
  43. const subscriptionKey = storeKey + 'Subscription'
  44. const version = hotReloadingVersion++
  45.  
  46. const contextTypes = {
  47. [storeKey]: storeShape,[subscriptionKey]: PropTypes.instanceOf(Subscription),}
  48. const childContextTypes = {
  49. [subscriptionKey]: PropTypes.instanceOf(Subscription)
  50. }
  51.  
  52. // 用户设置connect(mapStateToProps,mapDispatchToProps)(component)中component
  53. // 构成高阶组件
  54. return function wrapWithConnect(WrappedComponent) {
  55. invariant(
  56. typeof WrappedComponent == 'function',`You must pass a component to the function returned by ` +
  57. `connect. Instead received ${WrappedComponent}`
  58. )
  59.  
  60. const wrappedComponentName = WrappedComponent.displayName
  61. || WrappedComponent.name
  62. || 'Component'
  63.  
  64. const displayName = getDisplayName(wrappedComponentName)
  65.  
  66. const selectorFactoryOptions = {
  67. ...connectOptions,getDisplayName,methodName,renderCountProp,shouldHandleStateChanges,storeKey,withRef,displayName,wrappedComponentName,WrappedComponent
  68. }
  69.  
  70. class Connect extends Component {
  71. constructor(props,context) {
  72. super(props,context)
  73.  
  74. this.version = version
  75. this.state = {}
  76. this.renderCount = 0
  77. // Provider容器组件中,通过context.store向子组件传入Redux的store,storeKey默认为store
  78. // 未曾设置Provider的情形下呢????
  79. this.store = this.props[storeKey] || this.context[storeKey]
  80. // 父组件的subscription回调队列属性,当前为顶层组件时为null
  81. this.parentSub = props[subscriptionKey] || context[subscriptionKey]
  82.  
  83. this.setWrappedInstance = this.setWrappedInstance.bind(this)
  84.  
  85. invariant(this.store,`Could not find "${storeKey}" in either the context or ` +
  86. `props of "${displayName}". ` +
  87. `Either wrap the root component in a <Provider>,` +
  88. `or explicitly pass "${storeKey}" as a prop to "${displayName}".`
  89. )
  90.  
  91. // getState引用当前组件相应Redux的store.getState
  92. this.getState = this.store.getState.bind(this.store);
  93.  
  94. // 构建this.selector属性,其中props方法获取当前的props,run方法更新props(引用对象形式)
  95. this.initSelector()
  96.  
  97. // 构建this.subscription回调函数队列,构建subscription.onStateChange方法,但不挂载
  98. // componentDidMount方法中,顶层组件redux.store回调队列中挂载父子组件的onStateChange方法
  99. // redux.store.dispatch方法执行时,触发父子组件的onStateChange方法
  100. // 更新嵌套组件的props,同时按shouldComponentUpdate条件触发组件重绘
  101. this.initSubscription()
  102. }
  103.  
  104. // 将subscription回调队列属性传递给子组件,或者将祖先组件的subscription传递给子组件
  105. getChildContext() {
  106. return { [subscriptionKey]: this.subscription || this.parentSub }
  107. }
  108.  
  109. // 挂载父子组件的onStateChange方法,绑定dispatch方法触发时更新组件的props属性以及重绘组件
  110. // connect方法执行过程中,由redux.store.state初始化数据更新组件props组件属性
  111. componentDidMount() {
  112. if (!shouldHandleStateChanges) return
  113.  
  114. // 顶层组件redux.store、this.subscrption回调队列中挂载父子组件的onStateChange方法
  115. this.subscription.trySubscribe()
  116. // connect(mapStateToProps,mapDispatchToProps)方法执行时
  117. // redux.store.state初始化绑定到react组件props属性过程中,是否更新组件props属性
  118. // 以及重绘组件,默认不重绘???
  119. this.selector.run(this.props)
  120. if (this.selector.shouldComponentUpdate) this.forceUpdate()
  121. }
  122.  
  123. // 由组件更新后、重绘前的props,触发redux.store.dispatch方法更新props,用于重绘
  124. componentWillReceiveProps(nextProps) {
  125. this.selector.run(nextProps)
  126. }
  127.  
  128. // 判断组件是否已由redux机制进行重绘
  129. shouldComponentUpdate() {
  130. return this.selector.shouldComponentUpdate
  131. }
  132.  
  133. // 组件取消挂载时释放内存,即connect(mapStateToProps,mapDispatchToProps)(component)中component
  134. componentWillUnmount() {
  135. if (this.subscription) this.subscription.tryUnsubscribe()
  136.  
  137. this.subscription = null
  138. this.store = null
  139. this.parentSub = null
  140. this.selector.run = () => {}
  141. }
  142.  
  143. // 获取被包裹的UI组件
  144. getWrappedInstance() {
  145. invariant(withRef,`To access the wrapped instance,you need to specify ` +
  146. `{ withRef: true } in the options argument of the ${methodName}() call.`
  147. )
  148. return this.wrappedInstance
  149. }
  150.  
  151. setWrappedInstance(ref) {
  152. this.wrappedInstance = ref
  153. }
  154.  
  155. // 构建this.selector属性,其中props方法获取当前的props,run方法更新props
  156. // 通过redux.store.state更新、redux.store.dispatch方法触发获取最新的props
  157. initSelector() {
  158. const { dispatch } = this.store
  159. const { getState } = this;
  160. // 返回react.props计算函数,返回函数在redux.store.dispatch派发action事件时执行
  161. const sourceSelector = selectorFactory(dispatch,selectorFactoryOptions)
  162.  
  163. const selector = this.selector = {
  164. shouldComponentUpdate: true,props: sourceSelector(getState(),this.props),// 重新计算react.props
  165. run: function runComponentSelector(props) {
  166. try {
  167. const nextProps = sourceSelector(getState(),props)
  168. if (selector.error || nextProps !== selector.props) {
  169. selector.shouldComponentUpdate = true
  170. selector.props = nextProps
  171. selector.error = null
  172. }
  173. } catch (error) {
  174. selector.shouldComponentUpdate = true
  175. selector.error = error
  176. }
  177. }
  178. }
  179. }
  180.  
  181. // 构建this.subscription回调函数队列,构建subscription.onStateChange方法,但不挂载
  182. // 顶层组件subscription回调函数队列的onStateChange方法由本组件Redux.store.dispatch触发执行
  183. // 子组件的onStateChange方法由顶层组件Redux.store.dispatch触发顶层组件相应的onStateChange方法
  184. // 最终通过调用顶层组件subscription.notifyNestedSubs方法触发执行
  185. // onStateChange方法用于更新嵌套组件的props,同时按shouldComponentUpdate条件触发组件重绘
  186. initSubscription() {
  187. if (shouldHandleStateChanges) {
  188. const subscription = this.subscription = new Subscription(this.store,this.parentSub)
  189. const dummyState = {}
  190.  
  191. // 在Subsciption模块中,通过redux.store.dispatch方法触发父子组件的this.subscription.onStateChange
  192. // 更新嵌套组件的props,同时按shouldComponentUpdate条件触发组件重绘
  193. subscription.onStateChange = function onStateChange() {
  194. // 更新组件的props
  195. this.selector.run(this.props)
  196.  
  197. // this.selector.shouldComponentUpdate为真值重绘当前组件,否则更新子组件的props、按条件重绘子组件
  198. if (!this.selector.shouldComponentUpdate) {
  199. subscription.notifyNestedSubs()
  200. } else {
  201. // 更新组件完成后执行回调,
  202. this.componentDidUpdate = function componentDidUpdate() {
  203. this.componentDidUpdate = undefined
  204. subscription.notifyNestedSubs()
  205. }
  206.  
  207. // 调用setState更新react组件,setState方法不论prevState、currentState改变与否
  208. // 都会比较组件的props进行重绘???
  209. this.setState(dummyState)
  210. }
  211. }.bind(this)
  212. }
  213. }
  214.  
  215. // 判断顶层组件的store及subscription回调函数队列是否挂载父子组件的onStateChange方法
  216. isSubscribed() {
  217. return Boolean(this.subscription) && this.subscription.isSubscribed()
  218. }
  219.  
  220. // 通过selector.props添加额外的属性,当组件更新时,又会发生怎样的情况???
  221. addExtraProps(props) {
  222. if (!withRef && !renderCountProp) return props
  223. // make a shallow copy so that fields added don't leak to the original selector.
  224. // this is especially important for 'ref' since that's a reference back to the component
  225. // instance. a singleton memoized selector would then be holding a reference to the
  226. // instance,preventing the instance from being garbage collected,and that would be bad
  227. const withExtras = { ...props }
  228. if (withRef) withExtras.ref = this.setWrappedInstance
  229. if (renderCountProp) withExtras[renderCountProp] = this.renderCount++
  230. return withExtras
  231. }
  232.  
  233. render() {
  234. const selector = this.selector
  235. // 初始化渲染时,以redux更新props后,不予的重绘???
  236. selector.shouldComponentUpdate = false
  237.  
  238. if (selector.error) {
  239. throw selector.error
  240. } else {
  241. return createElement(WrappedComponent,this.addExtraProps(selector.props))
  242. }
  243. }
  244. }
  245.  
  246. Connect.WrappedComponent = WrappedComponent
  247. Connect.displayName = displayName
  248. Connect.childContextTypes = childContextTypes
  249. Connect.contextTypes = contextTypes
  250. Connect.propTypes = contextTypes
  251.  
  252. // 开发环境,保证props可由redux机制顺利更新,并完成组件重绘
  253. if (process.env.NODE_ENV !== 'production') {
  254. Connect.prototype.componentWillUpdate = function componentWillUpdate() {
  255. if (this.version !== version) {
  256. this.version = version
  257. this.initSelector()
  258.  
  259. if (this.subscription) this.subscription.tryUnsubscribe()
  260. this.initSubscription()
  261. if (shouldHandleStateChanges) this.subscription.trySubscribe()
  262. }
  263. }
  264. }
  265.  
  266. return hoistStatics(Connect,WrappedComponent)
  267. }
  268. }

mapStateToProps.js、mapDispatchToProps.js、wrapMapToProps.js、mergeProps.js

  1. // mapStateToProps.js
  2. import { wrapMapToPropsConstant,wrapMapToPropsFunc } from './wrapMapToProps'
  3.  
  4. // 当用户配置的mapStateToProps是函数时,使用wrapMapToPropsFunc装饰mapStateToProps
  5. // 传入redux的dispatch方法、react组件的displayName
  6. export function whenMapStateToPropsIsFunction(mapStateToProps) {
  7. return (typeof mapStateToProps === 'function')
  8. ? wrapMapToPropsFunc(mapStateToProps,'mapStateToProps')
  9. : undefined
  10. }
  11.  
  12. // 当用户配置的mapStateToProps不是函数时,设置默认的mapStateToProps为空函数;否则不设置
  13. export function whenMapStateToPropsIsMissing(mapStateToProps) {
  14. return (!mapStateToProps)
  15. ? wrapMapToPropsConstant(() => ({}))
  16. : undefined
  17. }
  18.  
  19. // 当用户配置的mapStateToProps是函数时,使用wrapMapToPropsFunc装饰mapStateToProps
  20. // 传入redux的dispatch方法、react组件的displayName
  21. // 当用户配置的mapStateToProps不是函数时,设置默认的mergeProps为空函数;否则不设置
  22. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  23. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性
  24. export default [
  25. whenMapStateToPropsIsFunction,whenMapStateToPropsIsMissing
  26. ]
  27.  
  28.  
  29.  
  30. // mapDispatchToProps.js
  31. import { bindActionCreators } from 'redux'
  32. import { wrapMapToPropsConstant,wrapMapToPropsFunc } from './wrapMapToProps'
  33.  
  34. // 当用户配置的mapDispatchToProps是函数时,使用wrapMapToPropsFunc装饰mapDispatchToProps
  35. // 传入redux的dispatch方法、react组件的displayName
  36. export function whenMapDispatchToPropsIsFunction(mapDispatchToProps) {
  37. return (typeof mapDispatchToProps === 'function')
  38. ? wrapMapToPropsFunc(mapDispatchToProps,'mapDispatchToProps')
  39. : undefined
  40. }
  41.  
  42. // 当用户配置的mapDispatchToProps不是函数时,设置默认的mapDispatchToProps为输出redux.store.dispatch方法;否则不设置
  43. export function whenMapDispatchToPropsIsMissing(mapDispatchToProps) {
  44. return (!mapDispatchToProps)
  45. ? wrapMapToPropsConstant(dispatch => ({ dispatch }))
  46. : undefined
  47. }
  48.  
  49. // 当用户配置的mapDispatchToProps是对象时,调用bindActionCreators生成特定派发方法;否则返回undefined
  50. export function whenMapDispatchToPropsIsObject(mapDispatchToProps) {
  51. return (mapDispatchToProps && typeof mapDispatchToProps === 'object')
  52. ? wrapMapToPropsConstant(dispatch => bindActionCreators(mapDispatchToProps,dispatch))
  53. : undefined
  54. }
  55.  
  56. // 当用户配置的mapDispatchToProps是函数时,使用wrapMapToPropsFunc装饰mapDispatchToProps
  57. // 传入redux的dispatch方法、react组件的displayName
  58. // 当用户配置的mapDispatchToProps不是函数时,设置默认的mapDispatchToProps为输出redux.store.dispatch方法;否则不设置
  59. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  60. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性
  61. export default [
  62. whenMapDispatchToPropsIsFunction,whenMapDispatchToPropsIsMissing,whenMapDispatchToPropsIsObject
  63. ]
  64.  
  65.  
  66.  
  67. // wrapMapToProps.js
  68. // 普通对象校验
  69. import verifyPlainObject from '../utils/verifyPlainObject'
  70.  
  71. // 当用户配置的mapDispatchToProps为对象形式时,在mapDispatchToProps模块的whenMapDispatchToPropsIsObject函数调用
  72. // 参数getConstant为dispatch => bindActionCreators(mapDispatchToProps,dispatch)函数
  73. // 接受dispatch作为参数,生成特定派发action的方法,对象形式,最终挂载给react组件的props属性
  74. // 即调用props.actionname派发特定的action
  75. // 返回函数形式;同用户配置的mapDispatchToProps为函数时统一接口,为函数时需要接受dispatch方法作为参数
  76. // 函数返回值为对象形式,用于更新react组件的props属性
  77. export function wrapMapToPropsConstant(getConstant) {
  78. return function initConstantSelector(dispatch,options) {
  79. const constant = getConstant(dispatch,options)
  80.  
  81. function constantSelector() { return constant }
  82. // react-redux自动派发action时,不需要根据react原有的props去判断派发何种action
  83. constantSelector.dependsOnOwnProps = false
  84. return constantSelector
  85. }
  86. }
  87.  
  88. // 通过redux的state、dispatch更新react组件的props时,是否需要原有的props作为参数,就此形成新的props
  89. // 用户配置的mapStateToProps、mapDispatchToProps为函数,可添加dependsOnOwnProps属性
  90. // 当其为真值时,意味通过redux的state、dispatch更新react组件的props时,需要原有的props作为参数
  91. export function getDependsOnOwnProps(mapToProps) {
  92. return (mapToProps.dependsOnOwnProps !== null && mapToProps.dependsOnOwnProps !== undefined)
  93. ? Boolean(mapToProps.dependsOnOwnProps)
  94. : mapToProps.length !== 1
  95. }
  96.  
  97. // 当用户配置的mapStateToProps(即mapStateToProps、mapDispatchToProps)为函数形式时
  98. // 参数methodName校验提示用,由connect模块通过match方法调用mapStateToProps或mapDispatchToProps模块传入
  99. // 在connect模块中构建initProxySelector函数
  100. // initProxySelector在sconnectAdvanced模块中接受redux.dispatch、react.displayName作为参数
  101. // 返回mapToPropsProxy封装函数
  102. // mapToPropsProxy在selectorFactory模块中接受redux.state|dispatch、react.displayName作为参数
  103. // 正式用户配置的mapStateToProps或mapDispatchToProps函数,更新react.props
  104. export function wrapMapToPropsFunc(mapToProps,methodName) {
  105. // selectorFactory模块中调用,返回值赋给mapStateToProps或mapDispatchToProps
  106. // 参数dispatch为容器store的dispatch方法,displayName为容器的displayName
  107. return function initProxySelector(dispatch,{ displayName }) {
  108.  
  109. const proxy = function mapToPropsProxy(stateOrDispatch,ownProps) {
  110. return proxy.dependsOnOwnProps
  111. ? proxy.mapToProps(stateOrDispatch,ownProps)
  112. : proxy.mapToProps(stateOrDispatch)
  113. }
  114.  
  115. // 判断通过redux的state、dispatch更新react组件的props时,是否需要原有的props作为参数,就此形成新的props
  116. proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps)
  117.  
  118. // 参数stateOrDispatch、ownProps在selectorFactory模块中传入
  119. // 针对mapStateToProps传入state,针对mapDispatchToProps传入dispatch
  120. // 通过proxy.mapToProps方法执行过程中按条件重写proxy.mapToProps,构成递归调用proxy.mapToProps
  121. // 第一次调用proxy.mapToProps,动态传入react组件原有的props
  122. // 第二次调用proxy.mapToProps,执行用户配置的mapStateToProps、mapDispatchToProps更新props
  123. // 第三次调用proxy.mapToProps,当mapDispatchToProps返回执行redux.store.dispatch的函数
  124. // 通过递归调用更新props
  125. proxy.mapToProps = function detectFactoryAndVerify(stateOrDispatch,ownProps) {
  126. // 重新设定proxy.mapToProps为用户传入的mapToProps函数(即mapStateToProps、mapDispatchToProps)
  127. // 当再次调用proxy函数时将获取mapToProps返回对象并执行
  128. proxy.mapToProps = mapToProps
  129. let props = proxy(stateOrDispatch,ownProps)
  130.  
  131. // 用户传入的mapToProps函数(即mapStateToProps、mapDispatchToProps)返回函数
  132. // 通常是mapDispatchToProps,需要通过执行redux.store.dispatch更新props
  133. // 再次调用proxy获取函数的返回对象
  134. if (typeof props === 'function') {
  135. proxy.mapToProps = props
  136. proxy.dependsOnOwnProps = getDependsOnOwnProps(props)
  137. props = proxy(stateOrDispatch,ownProps)
  138. }
  139.  
  140. // 校验props为普通对象
  141. if (process.env.NODE_ENV !== 'production') verifyPlainObject(props,methodName)
  142.  
  143. // 用户传入的mapToProps函数返回值,对象形式
  144. // 即connect接口接受的mapStateToProps或mapDispatchToProps参数函数返回值
  145. return props
  146. }
  147.  
  148. return proxy
  149. }
  150. }
  151.  
  152.  
  153.  
  154. // mergeProps.js
  155. // 普通对象校验
  156. import verifyPlainObject from '../utils/verifyPlainObject'
  157.  
  158. // 默认的mergeProps,原样输出stateProps,dispatchProps,ownProps
  159. export function defaultMergeProps(stateProps,ownProps) {
  160. return { ...ownProps,...stateProps,...dispatchProps }
  161. }
  162.  
  163. // 装饰用户配置的mergeProps,传入redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual
  164. export function wrapMergePropsFunc(mergeProps) {
  165. // 将redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual等属性传入mergeProps
  166. // 用于警告提示或者mergeProps方法中使用,mergeProps中可直接使用dispatch方法
  167. return function initMergePropsProxy(
  168. dispatch,{ displayName,areMergedPropsEqual }
  169. ) {
  170. let hasRunOnce = false
  171. let mergedProps// 缓存前一次混合mergedProps
  172.  
  173. return function mergePropsProxy(stateProps,ownProps) {
  174. // mergeProps(stateProps,ownProps)
  175. // 将mapStateToProps获得的stateProps、mapDispatchToProps获得的dispatchProps、
  176. // 以及react组件原有的ownProps,混合为新的props
  177. const nextMergedProps = mergeProps(stateProps,ownProps)
  178.  
  179. // redux.dispatch事件触发时,傻瓜式重新计算混合props或优化计算props
  180. if (hasRunOnce) {
  181. if (!pure || !areMergedPropsEqual(nextMergedProps,mergedProps))
  182. mergedProps = nextMergedProps
  183.  
  184. // react和redux初始化关联时,返回初次计算生成的nextMergedProps
  185. } else {
  186. hasRunOnce = true
  187. mergedProps = nextMergedProps
  188.  
  189. // 校验mergedProps为普通对象
  190. if (process.env.NODE_ENV !== 'production')
  191. verifyPlainObject(mergedProps,'mergeProps')
  192. }
  193.  
  194. return mergedProps
  195. }
  196. }
  197. }
  198.  
  199. // 当用户配置的mergeProps是函数时,使用wrapMergePropsFunc装饰mergeProps
  200. // 传入redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual
  201. // 当用户配置的mergeProps不是函数时,返回undefined
  202. export function whenMergePropsIsFunction(mergeProps) {
  203. return (typeof mergeProps === 'function')
  204. ? wrapMergePropsFunc(mergeProps)
  205. : undefined
  206. }
  207.  
  208. // 当用户配置的mergeProps不是函数时,设置默认的mergeProps为defaultMergeProps;否则不设置
  209. export function whenMergePropsIsOmitted(mergeProps) {
  210. return (!mergeProps)
  211. ? () => defaultMergeProps
  212. : undefined
  213. }
  214.  
  215. // 当用户配置的mergeProps是函数时,使用wrapMergePropsFunc装饰mergeProps
  216. // 传入redux的dispatch方法、react组件的displayName、pure、areMergedPropsEqual
  217. // 当用户配置的mergeProps不是函数时,设置默认的mergeProps为defaultMergeProps
  218. // 接受待装饰函数,返回装饰函数构造器,执行后装饰函数
  219. // 数组项在connect模块的match函数中挨个调用输出为真值时即返回,增加编码的灵活性
  220. export default [
  221. whenMergePropsIsFunction,whenMergePropsIsOmitted
  222. ]

selectorFactory.js、verifySubselectors.js

  1. // selectorFactory.js
  2. // 开发环境校验最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps为真值
  3. // 提示最终装饰函数mapStateToProps、mapDispatchToProps不需要react组件原有props传参
  4. import verifySubselectors from './verifySubselectors'
  5. // redux.dispatch派发action事件触发时,傻瓜式重新计算react.props
  6. export function impureFinalPropsSelectorFactory(
  7. mapStateToProps,dispatch
  8. ) {
  9. return function impureFinalPropsSelector(state,ownProps) {
  10. return mergeProps(
  11. mapStateToProps(state,ownProps),mapDispatchToProps(dispatch,ownProps
  12. )
  13. }
  14. }
  15.  
  16. // 定义最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps的执行机制
  17. // 按条件分为初始化执行,调用handleFirstCall函数;再次执行,调用pureFinalPropsSelector
  18. // 并传入redux相关的state、dispatch属性,react相关的ownProps属性
  19. // 返回函数,用于重新获取react组件的props
  20. // 与impureFinalPropsSelectorFactory的差别时
  21. // impureFinalPropsSelectorFactory每次触发redux.dispatch,均重新计算react.props
  22. // pureFinalPropsSelectorFactory是优化计算方案,state、props改变时才重新计算
  23. export function pureFinalPropsSelectorFactory(
  24. mapStateToProps,dispatch,{ areStatesEqual,areStatePropsEqual }
  25. ) {
  26. let hasRunAtLeastOnce = false// redux.store同react.props是否关联过一次标识
  27. let state// 缓存上一次redux.store.state
  28. let ownProps// 缓存上一次react.props
  29. let stateProps// 缓存上一次redux.store.state赋值给react.props的属性
  30. let dispatchProps// 缓存上一次redux.store.dispatch构造的特定派发action方法赋值给react.props的属性
  31. let mergedProps// 缓存stateProps、dispatchProps、ownProps复合集,react组件待更新的props
  32.  
  33. // 初始化将redux.store.state、redux.store.dispatch按条件赋值给react.props
  34. function handleFirstCall(firstState,firstOwnProps) {
  35. state = firstState
  36. ownProps = firstOwnProps
  37.  
  38. // 将redux.store.state赋值给react.props,特定情况下需要react组件原有的props设定赋值情况
  39. stateProps = mapStateToProps(state,ownProps)
  40.  
  41. // 将redux.store.dispatch构造的特定派发action方法赋值给react.props
  42. // 特定情况下需要react组件原有的props设定赋值情况
  43. dispatchProps = mapDispatchToProps(dispatch,ownProps)
  44.  
  45. // 混合stateProps、dispatchProps赋值给react.props,特定情况下需要react组件原有的props设定赋值情况
  46. mergedProps = mergeProps(stateProps,ownProps)
  47.  
  48. hasRunAtLeastOnce = true
  49. return mergedProps
  50. }
  51.  
  52. // redux的dispatch触发且react组件props改变时,重新获取redux.store.state、redux.store.dispatch相应属性
  53. // 按条件赋值给react.props
  54. function handleNewPropsAndNewState() {
  55. // 因redux的dispatch触发、react组件props改变,重新将redux.store.state绑定在react.props属性
  56. stateProps = mapStateToProps(state,ownProps)
  57.  
  58. // 因react.props变动,重新将redux.dispatch特定的派发方法绑定在react.props属性
  59. if (mapDispatchToProps.dependsOnOwnProps)
  60. dispatchProps = mapDispatchToProps(dispatch,ownProps)
  61.  
  62. mergedProps = mergeProps(stateProps,ownProps)
  63. return mergedProps
  64. }
  65.  
  66. // react组件props改变时,重新获取redux.store.state、redux.store.dispatch相应属性,按条件赋值给react.props
  67. function handleNewProps() {
  68. if (mapStateToProps.dependsOnOwnProps)
  69. stateProps = mapStateToProps(state,ownProps)
  70. return mergedProps
  71. }
  72.  
  73. // redux的dispatch触发,引起state改变时,重新获取redux.store.state,按条件赋值给react.props
  74. // redux机制,dispatch(action)触发事件后,state在回调函数执行前已改变
  75. function handleNewState() {
  76. const nextStateProps = mapStateToProps(state,ownProps)
  77. const statePropsChanged = !areStatePropsEqual(nextStateProps,stateProps)
  78. stateProps = nextStateProps
  79. if (statePropsChanged)
  80. mergedProps = mergeProps(stateProps,ownProps)
  81.  
  82. return mergedProps
  83. }
  84. // redux.dispatch事件触发时,重新将redux.store.state、redux.store.dispatch按条件赋值给react.props
  85. // react.props改变需要在redux.dispatch事件触发过程中发生
  86. function handleSubsequentCalls(nextState,nextOwnProps) {
  87. // 默认判断react.props是否修改,需要重新将redux.state、redux.dispatch按条件赋值给react.props
  88. // 用户重写判断机制,可以实现修改react.props部分属性时,避过react-redux通过redux.store重新计算props
  89. const propsChanged = !areOwnPropsEqual(nextOwnProps,ownProps)
  90. // 默认判断redux.state是否修改,需要重新将redux.state、redux.dispatch按条件赋值给react.props
  91. // 用户重写判断机制,可以实现修改redux.state部分属性时,避过react-redux通过redux.store重新计算props
  92. const stateChanged = !areStatesEqual(nextState,state)
  93.  
  94. state = nextState
  95. ownProps = nextOwnProps
  96.  
  97. // redux的dispatch触发且react组件props改变时,重新获取redux.store.state、redux.store.dispatch相应属性
  98. // 按条件赋值给react.props
  99. if (propsChanged && stateChanged) return handleNewPropsAndNewState()
  100.  
  101. // react组件props改变时,重新获取redux.store.state、redux.store.dispatch相应属性,按条件赋值给react.props
  102. if (propsChanged) return handleNewProps()
  103.  
  104. // redux的dispatch触发,引起state改变时,重新获取redux.store.state,按条件赋值给react.props
  105. if (stateChanged) return handleNewState()
  106.  
  107. // redux的dispatch未曾触发且react组件props未曾改变,直接返回前一次props
  108. return mergedProps
  109. }
  110.  
  111. // 返回函数,优点是可以使用闭包变量缓存前次的state及ownProps
  112. // 定义最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps的执行机制
  113. // 传入redux相关的state、dispatch属性,react相关的ownProps属性
  114. return function pureFinalPropsSelector(nextState,nextOwnProps) {
  115. return hasRunAtLeastOnce
  116. ? handleSubsequentCalls(nextState,nextOwnProps)
  117. : handleFirstCall(nextState,nextOwnProps)
  118. }
  119. }
  120.  
  121. // connectAdvanced模块中调用,通过connect模块传入,返回react.props计算函数
  122. // 参数dispatch为redux.store的dispatch方法,次参对象为react组件的属性
  123. // 各参数传给装饰函数initMapStateToProps、initMapDispatchToProps、initMergeProps
  124. // 获取mapStateToProps、mapDispatchToProps、mergeProps计算react组件待变更的props
  125. export default function finalPropsSelectorFactory(dispatch,{
  126. initMapStateToProps,...options
  127. }) {
  128. // 获取最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps,用以计算计算react组件待变更的props
  129. const mapStateToProps = initMapStateToProps(dispatch,options)
  130. const mapDispatchToProps = initMapDispatchToProps(dispatch,options)
  131. const mergeProps = initMergeProps(dispatch,options)
  132.  
  133. // 开发环境校验最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps为真值
  134. // 提示最终装饰函数mapStateToProps、mapDispatchToProps不需要react组件原有props传参
  135. if (process.env.NODE_ENV !== 'production') {
  136. verifySubselectors(mapStateToProps,options.displayName)
  137. }
  138.  
  139. // options.pure在connect模块中设置默认为真值
  140. const selectorFactory = options.pure
  141. ? pureFinalPropsSelectorFactory// 傻瓜式计算react.props
  142. : impureFinalPropsSelectorFactory// 优化计算react.props
  143.  
  144. // 定义最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps调用机制,并传入dispatch、options参数
  145. // 返回react.props计算函数
  146. return selectorFactory(
  147. mapStateToProps,options
  148. )
  149. }
  150.  
  151.  
  152.  
  153. // verifySubselectors.js
  154. import warning from '../utils/warning'
  155.  
  156. function verify(selector,displayName) {
  157. // 校验最终装饰函数mapStateToProps、mapDispatchToProps、mergeProps为真值
  158. if (!selector) {
  159. throw new Error(`Unexpected value for ${methodName} in ${displayName}.`)
  160.  
  161. // 提示最终装饰函数mapStateToProps、mapDispatchToProps不需要react组件原有props传参
  162. } else if (methodName === 'mapStateToProps' || methodName === 'mapDispatchToProps') {
  163. if (!selector.hasOwnProperty('dependsOnOwnProps')) {
  164. warning(
  165. `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.`
  166. )
  167. }
  168. }
  169. }
  170.  
  171. export default function verifySubselectors(mapStateToProps,displayName) {
  172. verify(mapStateToProps,'mapStateToProps',displayName)
  173. verify(mapDispatchToProps,'mapDispatchToProps',displayName)
  174. verify(mergeProps,'mergeProps',displayName)
  175. }

Subscription.js

  1. const CLEARED = null
  2. const nullListeners = { notify() {} }
  3.  
  4. // 类似jquery的Callbacks回调函数队列,用于向队列next中添加和移除回调函数,以及触发回调函数的执行
  5. function createListenerCollection() {
  6. let current = []
  7. let next = []
  8.  
  9. return {
  10. clear() {
  11. next = CLEARED
  12. current = CLEARED
  13. },notify() {
  14. const listeners = current = next
  15. for (let i = 0; i < listeners.length; i++) {
  16. listeners[i]()
  17. }
  18. },subscribe(listener) {
  19. let isSubscribed = true
  20. if (next === current) next = current.slice()
  21. next.push(listener)
  22.  
  23. return function unsubscribe() {
  24. if (!isSubscribed || current === CLEARED) return
  25. isSubscribed = false
  26.  
  27. if (next === current) next = current.slice()
  28. next.splice(next.indexOf(listener),1)
  29. }
  30. }
  31. }
  32. }
  33.  
  34. // 通过向react组件挂载this.subscription对象
  35. // 将当前组件及其子孙组件的subscription.onStateChange绑定为redux.stroe.dispatch方法的回调
  36. // subscription.onStateChange方法中,调用this.selector.run重新计算props
  37. // 本层组件的onStateChange方法通过redux.store.subscribe绑定为回调函数
  38. // 同时本层组件的onStateChange触发this.subscription.notifyNestedSubs方法
  39. // 而子组件的onStateChange通过this.subscription.addNestedSub绑定为回调函数
  40. // 这样redux.store.dispatch就可以触发父子组件的props更新
  41. export default class Subscription {
  42. constructor(store,parentSub) {
  43. this.store = store
  44. this.parentSub = parentSub
  45. this.unsubscribe = null
  46. this.listeners = nullListeners
  47. }
  48.  
  49. // 添加回调函数,默认内部subscription方法使用
  50. // 向父组件的subscription回调函数队列添加子组件subscription对象的onStateChange方法
  51. addNestedSub(listener) {
  52. this.trySubscribe()
  53. return this.listeners.subscribe(listener)
  54. }
  55.  
  56. // 触发回调函数执行,默认connectAdvanced模块构建的onStateChange方法内使用
  57. // 父组件的subscription回调函数队列触发子组件subscription对象的onStateChange方法
  58. notifyNestedSubs() {
  59. this.listeners.notify()
  60. }
  61.  
  62. // 顶层组件的store及subscription回调函数队列是否挂载父子组件的onStateChange方法
  63. isSubscribed() {
  64. return Boolean(this.unsubscribe)
  65. }
  66.  
  67. // 挂载this.onStateChange方法,用于重新获得props,触发this.setState更新组件
  68. // 当前组件为顶层组件,this.store挂载this.onStateChange方法
  69. // 当前组件为子组件,通过父组件的onStateChange调用subscription.notifyNestedSubs挂载this.onStateChange方法
  70. trySubscribe() {
  71. if (!this.unsubscribe) {
  72. // this.onStateChange is set by connectAdvanced.initSubscription()
  73. // 当前组件为顶层组件时,通过this.store.subscribe挂载this.onStateChange方法
  74. // 即通过this.store.dispatch方法触发state改变的同时,同时触发this.onStateChange方法
  75. // 当前组件为子组件时,通过父组件的onStateChange调用subscription.notifyNestedSubs
  76. // 触发子组件的onStateChange方法
  77. // 怎样更新组件???
  78. this.unsubscribe = this.parentSub
  79. ? this.parentSub.addNestedSub(this.onStateChange)
  80. : this.store.subscribe(this.onStateChange)
  81. this.listeners = createListenerCollection()
  82. }
  83. }
  84.  
  85. tryUnsubscribe() {
  86. if (this.unsubscribe) {
  87. this.unsubscribe()
  88. this.unsubscribe = null
  89. this.listeners.clear()
  90. this.listeners = nullListeners
  91. }
  92. }
  93. }

shallowEqual.js、verifyPlainObject.js、warning.js、storeShape.js

  1. // shallowEqual.js、verifyPlainObject.js、warning.js、storeShape.js
  2. const hasOwn = Object.prototype.hasOwnProperty
  3.  
  4. // 比较变量是否全等,或者普通对象单层比较是否相同
  5. export default function shallowEqual(a,b) {
  6. if (a === b) return true
  7.  
  8. let countA = 0
  9. let countB = 0
  10. for (let key in a) {
  11. if (hasOwn.call(a,key) && a[key] !== b[key]) return false
  12. countA++
  13. }
  14.  
  15. for (let key in b) {
  16. if (hasOwn.call(b,key)) countB++
  17. }
  18.  
  19. return countA === countB
  20. }
  21.  
  22.  
  23.  
  24. // verifyPlainObject.js
  25. import isPlainObject from 'lodash/isPlainObject'
  26. import warning from './warning'
  27.  
  28. // 校验value是否普通对象
  29. export default function verifyPlainObject(value,methodName) {
  30. if (!isPlainObject(value)) {
  31. warning(
  32. `${methodName}() in ${displayName} must return a plain object. Instead received ${value}.`
  33. )
  34. }
  35. }
  36.  
  37.  
  38.  
  39. // warning.js
  40. // 打印错误或报错
  41. export default function warning(message) {
  42. /* eslint-disable no-console */
  43. if (typeof console !== 'undefined' && typeof console.error === 'function') {
  44. console.error(message)
  45. }
  46. /* eslint-enable no-console */
  47. try {
  48. throw new Error(message)
  49. /* eslint-disable no-empty */
  50. } catch (e) {}
  51. /* eslint-enable no-empty */
  52. }
  53.  
  54.  
  55.  
  56. // storeShape.js
  57. import { PropTypes } from 'react'
  58.  
  59. export default PropTypes.shape({
  60. subscribe: PropTypes.func.isrequired,dispatch: PropTypes.func.isrequired,getState: PropTypes.func.isrequired
  61. })

猜你在找的React相关文章