3

Redux源码分析之createStore - IslandZzzz

 2 years ago
source link: https://www.cnblogs.com/ltfxy/p/16424242.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Redux源码分析之createStore

createStore是一个高阶函数,主要作用是完成store的初始化
createStore(reducer,preloadedState,enhancer)

export default function createStore(reducer, preloadedState, enhancer) {

  // 只传两个参数并且第二个参数是函数的情况下,将其作为增强函数enhancer, 如createStore(reducer,applyMiddleware(middleWare))
  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.')
    }
    return enhancer(createStore)(reducer, preloadedState)
  }

  let currentReducer = reducer
  let currentState = preloadedState // 通过闭包维持一份createStore的state tree,更新时,current指针将指向dispatch生成的new state tree,  通过getStateapi对外暴露最新的state tree
  let currentListeners = []  // subscribe方法收集的订阅
  let nextListeners = currentListeners  // 用于调用ensureCanMutateNextListeners 浅拷贝一份list,防止用户在dispatching时调用subscribe/unsubscribe出现bug
  let isDispatching = false // 是否正在更新state
 
  function dispatch(action) {
    try {
      isDispatching = true
      // 改变当前状态
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
    // 在dispatch改变当前状态之后立即执行所有通过subscribe的函数,执行listener主要用于在更新状态之后做些什么事情,比如视图的render操作,我们可以根据最新的状态去渲染视图
    // 这种方式有一个缺点就是,不论你消费的数据有没有变化,只要你使用subscribe订阅了store,都会执行订阅函数
    // 也就是说,redux并不识别具体的订阅者,而是统一广播通知,但这一功能被react-redux实现了
    const listeners = (currentListeners = nextListeners)
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }
    return action
  }
  

  dispatch({ type: ActionTypes.INIT }) // 执行createStore完成状态初始化的时候,会在内部调用dispatch传递一个type为init的action, 并且返回一个store对象, 这也是唯一的一次非用户生成的action调度
  
  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  }
}

createStore的几个主要api

  • dispatch
  • subscribe/unsubscribe
  • getState

dispatch

负责响应用户的动作,派发action给reducer从而获取最新的视图状态

dispatch在初始化的时候由redux自身调用一次init action,其他时候都是用户由派发action调用

  1. dispatch将store的currentState指针指向reducer返回的new state
  2. 向用户广播通过subscribe注册的所有订阅
  3. 通过getState向用户暴露currentState
  function dispatch(action) {

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

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

    return action
  }

subscribe

store.subscribe(listener)
订阅redux 状态变化,一旦状态发生变化就执行所有的订阅函数,同时返回一个取消订阅的函数unsubscribe

  function subscribe(listener) {
    let isSubscribed = true
    nextListeners.push(listener)
    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }
      isSubscribed = false
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
      currentListeners = null
    }
  }

getState

createStore通过闭包维持一份state tree。
状态更新时, currentState指针将指向dispatch生成的new state tree, 并通过getState向外暴露

  function getState() {
    if (isDispatching) {
      throw new Error(
        'You may not call store.getState() while the reducer is executing. ' +
          'The reducer has already received the state as an argument. ' +
          'Pass it down from the top reducer instead of reading it from the store.'
      )
    }

    return currentState
  }

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK