整个redux的源码非常简单,所以解释很少,看代码就能看明白......

combineReducers


为啥先说这个

前提先看middleware: Redux-Middleware-源码解析, 这些都是解析createStore的前提


//传入的reducers是个对象//将多个reducer捆成一个export default function combineReducers(reducers) {  //取出所有reducer的key=> {key1:value,key2:value}  const reducerKeys =  .keys(reducers)  const finalReducers = {}  for (let i = 0; i < reducerKeys.length; i++) {    //取出key    const key = reducerKeys[i]    if (typeof reducers[key] === 'function') {      //可以代表的value是函数的话,保存进 finalReducers 对象中      finalReducers[key] = reducers[key]    }  }  //取出所有value是函数的key  const finalReducerKeys =  .keys(finalReducers)  let shapeAsserti   try {    assertReducerShape(finalReducers)  } catch (e) {    shapeAsserti  = e  }  //返回一个 combination 函数,方法接收state,action参数 这个返回的函数是createStore的第一个参数  return function combination(state = {}, action) {    if (shapeAsserti ) {      throw shapeAsserti     }    let hasChanged = false    const nextState = {}    //循环每一个reducer,    for (let i = 0; i < finalReducerKeys.length; i++) {      //取出key      const key = finalReducerKeys[i]      //取出key对应的reducer      const reducer = finalReducers[key]      //根据key在state获取状态      //state的状态都是根据reducer的名字进行存储的      const previousStateForKey = state[key]      //将state和action传入reducer中      const nextStateForKey = reducer(previousStateForKey, action)      //将nextStateForKey reducer 放入到nextState中      nextState[key] = nextStateForKey      //在state中的状态和reducer中返回的状态是否一样      hasChanged = hasChanged || nextStateForKey !== previousStateForKey    }    //返回新的state    return hasChanged ? nextState : state  }}

是什么

  1. 名字的含义就是组合reducer
  2. 因为reducers是作为createStore函数的第一个参数,而不是前多少个参数

干了什么


export default combineReducers({    userinfo,    stores,    home,    likeList})

  1. 其中的每一个参数都是一个reducer,而且每一个参数的名字都作为在store中的key
  2. 将这些reducer组合成一个reducers,提供给createStore作为参数

流程啥样

  1. 虽然传了很多reducer但是先过滤掉不是function的reducer(不知道不是function的reducer是啥)
  2. 将过滤的key存放到finalReducerKeys中,将过滤的reducer存放到finalReducers中,闭包要用
  3. 然后返回一个 combination() 函数,其实这个才是createStore的第一个参数

combination做了什么

  1. 循环每一个有效的reducer
  2. 取出reducer,state中的对应的状态
  3. 调用reducer,并传入取出的状态,和action,获取返回值(新state)
  4. 返回新的state

createStore


//创建store的api,也是redux中最重要的api,而创建的store用于管理应用中的所有state,且只有一个storeexport default function createStore(reducer, preloadedState, enhancer) {  //简而言之,第二个参数是函数,并且第三个参数是undefined,然后第二第三个参数值互换  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {    enhancer = preloadedState    preloadedState = undefined  }  if (typeof enhancer !== 'undefined') {    //这个就是中间件,看middleware那篇文章    return enhancer(createStore)(reducer, preloadedState)  }  //保存当前的reducer  let currentReducer = reducer  //保存传入的状态  let currentState = preloadedState  //设置当前监听集合  let currentListeners = []  //将当前的监听集合赋值给下一个监听集合  let nextListeners = currentListeners  let isDispatching = false    function ensureCanMutateNextListeners() {    if (nextListeners === currentListeners) {      //slice() 没有参数默认begin为0 就是拷贝下      nextListeners = currentListeners.slice()    }  }  //获取当前状态  //函数嵌套函数,内部函数引用外部函数的变量,最后返回函数,这是闭包  function getState() {    return currentState  }  //增加监听,参数listener是一个回调函数,在dispatch里,会调用所有的监听器  function subscribe(listener) {    let isSubscribed = true    ensureCanMutateNextListeners()    //把新增加的监听加入到当前监听列表中    nextListeners.push(listener)    //返回一个函数,用于去除监听    return function unsubscribe() {      if (!isSubscribed) {        return      }      //解除监听 isSubscribed 设置为false,意为已经取消监听      isSubscribed = false      ensureCanMutateNextListeners()      const index = nextListeners.indexOf(listener)      //然后干掉这个监听      nextListeners.splice(index, 1)    }  }  //这个是比较常用的api=>主要用于触发action,改变状态  function dispatch(action) {    try {      isDispatching = true//正在dispatch      //执行reducer 返回新state,调用的是combination()方法      currentState = currentReducer(currentState, action)    } finally {      // finally不管报没报错最后都要执行      isDispatching = false    }    //执行所有监听    const listeners = (currentListeners = nextListeners)    for (let i = 0; i < listeners.length; i++) {      const listener = listeners[i]      listener()    }    return action  }  //替换reducer 然后更新store  function replaceReducer(nextReducer) {    currentReducer = nextReducer    dispatch({ type: ActionTypes.REPLACE })  }  //这个是留给内部  function observable() {    const outerSubscribe = subscribe    return {      subscribe(observer) {        function observeState() {          if (observer.next) {            observer.next(getState())          }        }        observeState()        const unsubscribe = outerSubscribe(observeState)        return { unsubscribe }      },      [$$observable]() {        return this      }    }  }  //初始化store  dispatch({ type: ActionTypes.INIT })  return {    dispatch,    subscribe,    getState,    replaceReducer,    [$$observable]: observable  }}

是什么

  1. 这个是最核心的api,这个函数是创建store的唯一方式
  2. 并且返回了dispatch,subscribe,getState...比较常用的api

干了什么

const store = createStore(rootReducer, applyMiddleware(...middlewares));复制代码
  1. 如果有中间件,先处理中间件然后回过头来在执行createStore
  2. 保存了一些当前的属性,用于闭包,提供的api

api

getState

这个直接返回了当前的state,因为闭包,所以可以获取到最新的state

subscribe

负责新增监听,参数是个回调函数,将回调函数加入到监听集合,并且返回一个取消监听的函数:这个返回的函数内部封装了当执行时,在监听集合中将这个监听去掉

dispatch

是最核心的api,通过执行reducer(闭包,currentReducer),返回新的state,并赋值给当前的currentState,并执行所有的监听,返回action

replaceReducer

用于替换reducer,然后调用dispatch更新state


bindActionCreators

这个结合connect使用,在mapDispatchToProps中定义,就可以直接用this.props.userInfoActions来调用dispatch(action)操作


function mapStateToProps( state ) {    return {}}function mapDispatchToProps( dispatch ) {    return {        userInfoActions : bindActionCreators(userInfoActionsFormOtherFile, dispatch)    }}export default connect(    mapStateToProps,    mapDispatchToProps)(App)复制代码function bindActionCreator(actionCreator, dispatch) {  return function() {    return dispatch(actionCreator.apply(this, arguments))  }}export default function bindActionCreators(actionCreators, dispatch) {  //如果 actionCreators 是一个函数,染回 dispatch(actionCreator.apply(this, arguments))  if (typeof actionCreators === 'function') {    return bindActionCreator(actionCreators, dispatch)  }  //actionCreators 不是函数,不是对象,不是null  const keys =  .keys(actionCreators)  const boundActionCreators = {}  for (let i = 0; i < keys.length; i++) {    const key = keys[i]    const actionCreator = actionCreators[key]    if (typeof actionCreator === 'function') {      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)    }  }  //最后迭代actionCreators里的元素,如果是函数,就按照函数的方式组成数组,返回  return boundActionCreators}

是什么

就跟名字一样:给actionCreators绑定dispatch,也就是返回一个dispatch(actionCreator.apply(this, arguments))这样的函数,或者包含多个dispatch的数组

干了什么

  1. 传入两个参数,第一个是actionCreator,第二个是dispatch
  2. 如果只是一个actionCreator,那么直接返回一个包含dispatch(actionCreator.apply(this, arguments))的函数
  3. 如果他是个数组,就去循环这个数组将每一个actionCreator都绑定dispatch,然后返回这个数组

总结

看完了源码,感觉redux真的没有太多的东西,真是映射了那句话:用尽量少的代码,做尽量多的事情!

combineReducers

  1. 参数reducers是一个多个reducer组合的对象
  2. 去除所有的reducer的key=> reducerKeys
  3. 循环reducerKeys通过key取出reducer
  4. 如果reducer是个函数,就加进 finalReducers 中
  5. 取出finalReducers中的所有key=>finalReducerKeys
  6. 然后返回combination,这个是个内部函数,里面用到了上面的finalReducers和finalReducerKeys
  7. combination中取出每个reducer,根据finalReducerKeys中对应的key,在state中取出响应的状态
  8. 执行reducer并将参数传入返回新状态
  9. 将返回的状态添加进nextState对象中
  10. 返回新状态

通过代码的执行总结combineReducers

  1. 将多个reducer的对象reducers传入combineReducers中
  2. 返回 combination函数
  3. 返回的函数作为createStore的第一个参数
  4. 进入createStore中,提供的dispatch()中用到了reducers,并传入了state和action
  5. 然后执行combination函数,循环finalReducers
  6. 执行每一个reducer,通过返回的state,并添加进nextState对象中
  7. 返回的state和参数的state比较,如果两个state相等,则说明这个key所对应的state没有变化
  8. 如果不相等说明有变化,标记有变化
  9. 最后根据state是否有变化决定返回 nextState 还是参数 state


原文发布时间为:2018年06月26日
原文作者:mazy
本文来源: 掘金 如需转载请联系原作者

收藏 打印