美文网首页
Redux源码学习

Redux源码学习

作者: 占三疯 | 来源:发表于2017-07-13 18:06 被阅读74次

何为Redux,为什么Redux之类的概念东西我这边就不重复赘述了,可进入Redux官网查阅,以下是我在学习Redux的源码的一些个人总结.

我们可以先看看官方的文档,都有哪些API,从中也可以看出Redux中的一些方法是如何演化出来的.我们先看看index.js文件中的内容,代码有省略部分,最好是拿着源码一起看,Redux本身代码量并不大,只是其中用了很多的函数柯里化的方式,看着会比较晦涩

// index.js
export {
  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose
}

从以上代码可以看出来,就是Redux提供的API

createStore
import isPlainObject from 'lodash/isPlainObject'
import $$observable from 'symbol-observable'

/**
 *这就是初始化store状态树的action type
 */
export const ActionTypes = {
  INIT: '@@redux/INIT'
}

/**
 * 此函数接受三个参数,第一个参数是一个函数,就是我们的reduce函数,返回一个state
 */
export default function createStore(reducer, preloadedState, enhancer) {
  /**当preloadedState为函数且enhancer不存在时,将preloadedState赋值给enhancer并且将createStore传*入此函数
*/
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined
  }

  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
/**
*此处返回store提供的一些方法,如此处最后返回对象,只是其中的dispatch不一样,由applyMidware方法返回的组合函数而得到
*/
    return enhancer(createStore)(reducer, preloadedState)
  }

  if (typeof reducer !== 'function') {
    throw new Error('Expected the reducer to be a function.')
  }

  let currentReducer = reducer
  let currentState = preloadedState
  let currentListeners = []
  let nextListeners = currentListeners
  let isDispatching = false

  function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice()
    }
  }

  /**
   * 读取当前整个状态树
   */
  function getState() {
    return currentState
  }

  /**
   * dispatch订阅方法,当调用此方法时会在事件监听器中加入监听函数,当dispatch了一个action时,所有订  
 *阅的方法都会执行,此方法执行完成会返回一个取消订阅方法,用于取消订阅事件
   */
  function subscribe(listener) {
    if (typeof listener !== 'function') {
      throw new Error('Expected listener to be a function.')
    }

    let isSubscribed = true

    ensureCanMutateNextListeners()
    nextListeners.push(listener)

    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }

      isSubscribed = false

      ensureCanMutateNextListeners()
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }

  /**
   * dispatch函数接受一个为对象的参数,其中必须包含一个type属性,会将新的state赋值给currentState,并且会执行所有subscribe过的函数,并返回当前的action
   */
  function dispatch(action) {
    if (!isPlainObject(action)) {
      throw new Error(
        'Actions must be plain objects. ' +
        'Use custom middleware for async actions.'
      )
    }

    if (typeof action.type === 'undefined') {
      throw new Error(
        'Actions may not have an undefined "type" property. ' +
        'Have you misspelled a constant?'
      )
    }

    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }
    /** 改变当前dispatching状态为true,并且将更改后的state赋值给当前state
    */
    try {
      isDispatching = true
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
  // 当触发dispatching函数时,所有订阅的函数都会被触发
    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }

  /**
   * 此方法会将传入的reducer替换当前的reducer并进行Store初始化
   */
  function replaceReducer(nextReducer) {
    if (typeof nextReducer !== 'function') {
      throw new Error('Expected the nextReducer to be a function.')
    }

    currentReducer = nextReducer
    dispatch({ type: ActionTypes.INIT })
  }

  /**
   *不直接提供给开发者使用
   */
  function observable() {
    const outerSubscribe = subscribe
    return {

      subscribe(observer) {
        if (typeof observer !== 'object') {
          throw new TypeError('Expected the observer to be an object.')
        }

        function observeState() {
          if (observer.next) {
            observer.next(getState())
          }
        }

        observeState()
        const unsubscribe = outerSubscribe(observeState)
        return { unsubscribe }
      },

      [$$observable]() {
        return this
      }
    }
  }

  // 当一个store被创建的时候,会触发dispatch来初始化state
  dispatch({ type: ActionTypes.INIT })

  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}

createStore所作的事情其实很简单,主要的一个流程是,创建store,初始化state,返回一系列的方法,每个方法具体干了哪些事情,在上面的代码中都已经注释好了.其中有一些其他的波折的东西,我们一会会介绍

applyMiddleware
import compose from './compose'

/**
 *这个方法就是将一系列的中间件作为参数,将返回的函数作为createStore的第二个参数调用,最终结果
 *仍然会返回store提供的各个方法组成的对象,只是其中的dispatch方法是各个中间件组合成的一个组合
 * 函数,使得在调用dispatch的时候会经过各个中间件
 */
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    const store = createStore(reducer, preloadedState, enhancer)
    let dispatch = store.dispatch
    let chain = []
// 使用store提供的getState方法和dispatch方法供各个中间件使用
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
// 将所有的中间件中传入store实例提供的getState和dispatch方法,返回值为函数,通过compose方法整合出组合函数
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

applyMiddleware的方法主要是通过compose将各个中间件整合成一个组合函数,通过将store.dispatch传入函数中进行层层过滤,最终返回一个store

compose
/**
 * 从右到左整合成组合函数
 */

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

combineReducers
export default function combineReducers(reducers) {
  const reducerKeys = Object.keys(reducers)
  const finalReducers = {}
  for (let i = 0; i < reducerKeys.length; i++) {
    const key = reducerKeys[i]

    if (process.env.NODE_ENV !== 'production') {
      if (typeof reducers[key] === 'undefined') {
        warning(`No reducer provided for key "${key}"`)
      }
    }

    if (typeof reducers[key] === 'function') {
      finalReducers[key] = reducers[key]
    }
  }
  const finalReducerKeys = Object.keys(finalReducers)

  let unexpectedKeyCache
  if (process.env.NODE_ENV !== 'production') {
    unexpectedKeyCache = {}
  }

  let shapeAssertionError
  try {
    assertReducerShape(finalReducers)
  } catch (e) {
    shapeAssertionError = e
  }
// 最终返回的一个reducer,此函数在createStore的调用过程中,会将各个reducer的state组合成一个
//完整的state
  return function combination(state = {}, action) {
    if (shapeAssertionError) {
      throw shapeAssertionError
    }

    if (process.env.NODE_ENV !== 'production') {
      const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache)
      if (warningMessage) {
        warning(warningMessage)
      }
    }

    let hasChanged = false
    const nextState = {}
    for (let i = 0; i < finalReducerKeys.length; i++) {
      const key = finalReducerKeys[i]
      const reducer = finalReducers[key]
      const previousStateForKey = state[key]
      const nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? nextState : state
  }

以上代码的作用就是将多个拆分好的reducer最终组合成一个完整的reducer,其中store的key对应每一个state的key

bindActionCreators
function bindActionCreator(actionCreator, dispatch) {
  return (...args) => dispatch(actionCreator(...args))
}

/**
 */
export default function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch)
  }

  if (typeof actionCreators !== 'object' || actionCreators === null) {
    throw new Error(
      `bindActionCreators expected an object or a function, instead received ${actionCreators === null ? 'null' : typeof actionCreators}. ` +
      `Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?`
    )
  }

  const keys = Object.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)
    }
  }
  return boundActionCreators
}

以上代码的主要作用就是将action创建函数和之前创造的store所得到的dispatch方法传入,返回一个action绑定函数,调用这个绑定函数会自动dispatch利用actionCreate所创建的action

相关文章

网友评论

      本文标题:Redux源码学习

      本文链接:https://www.haomeiwen.com/subject/nqxghxtx.html