createStore几乎囊括了Redux的核心功能。

参数归一化

先看看createStore的函数签名:

export default function createStore(reducer, initialState, enhancer) {
  // ...
}

前两个参数比较常见,那么enhancer扮演了什么角色呢?

if (typeof initialState === 'function' && typeof enhancer === 'undefined') {
  enhancer = initialState
  initialState = undefined
}

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

  return enhancer(createStore)(reducer, initialState)
}

在enhancer(createStore)(reducer, initialState)调用中,enhancer对createStore的能力进行了增强,最终返回store。
典型使用案例是redux-devtools-extension,它将Redux DevTools做成浏览器插件。

初始状态及getState

完成基本参数校验后,在createStore中声明了如下变量及getState方法

  var currentReducer = reducer
  var currentState = initialState
  var currentListeners = []
  var nextListeners = currentListeners
  var isDispatching = false

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

  function getState() {
    return currentState
  }
  1. currentReducer:当前的reducer,支持通过store.replaceReducer方式动态替换reducer,为代码热替换提供了可能。
  2. currentState:应用的当前状态,默认为初始化时的状态。
  3. currentListeners、nextListeners:监听器
  4. isDispatching:某个action是否处于分发的处理过程中

getState方法用于返回当前状态。

subscribe、unsubscribe

在getState之后定义了store的subscribe方法

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

    var isSubscribed = true

    ensureCanMutateNextListeners()
    nextListeners.push(listener)

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

      isSubscribed = false

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

subscribe将listener添加到nextListeners中,unsubscribe可以删除这个listener。

dispatch

接下来就是dispatch

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.')
  }

  try {
    isDispatching = true
    currentState = currentReducer(currentState, action)
  } finally {
    isDispatching = false
  }

  var listeners = currentListeners = nextListeners
  for (var i = 0; i < listeners.length; i++) {
    listeners[i]()
  }

  return action
}

先是一些校验,然后将当前的状态和action传给当前的reducer,用于生成最新的state。再依次调用所有的监听器,通知状态的变更。最后返回action

replaceReducer

这个方法主要用于reducer的热替换,在开发过程中很少使用

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

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

dispatch({ type: ActionTypes.INIT })是为了拿到所有reducer中的初始状态,只用所有状态都成功获取后,Redux应用才能有条不紊地运作。

注:redux源码版本v3.5.2


小番茄
67 声望5 粉丝