首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redux源码解析系列 (三)-- createStore

Redux源码解析系列 (三)-- createStore

作者头像
IMWeb前端团队
发布2019-12-03 15:12:26
4640
发布2019-12-03 15:12:26
举报
文章被收录于专栏:IMWeb前端团队IMWeb前端团队

本文作者:IMWeb 黄qiong 原文出处:IMWeb社区 未经同意,禁止转载

createStore源码地址为:https://github.com/reactjs/redux/blob/master/src/createStore.js

下面我来对其进行解析~

INIT

这个方法是redux保留用的,用来初始化reducer的状态

export const ActionTypes = {
  INIT: '@@redux/INIT'
}

前面说 createStore的作用就是:创建一个store来管理app的状态,唯一改变状态的方式就是dispatch一个action,最终返回一个object。

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

不过replaceReducer,跟$$observable:都不常用~ ,所以这里只对前三的接口做解析。

createStore

在一个app里,只能有一个store,如果你想指明不同的state对应不同的action,可以用combineReducers去合并不同的reducer。

参数:

  • reducer(function):就是通过传入当前State,还有action,计算出下一个state,返回回来。
  • preloadedState(any):initial state
  • enhancer(function):增强store的功能,让它拥有第三方的功能,比如middleware.Redux里面唯一的enhancer就是applyMiddleware()
export default function createStore(reducer, preloadedState, enhancer) {
// 第一段说的就是当第二个参数没有传preloadedState,而直接传function的话,就会直接把这个function当成enhancer
  if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
    enhancer = preloadedState
    preloadedState = undefined
  }
  // 当第三个参数传了但是不是function也会报错
  if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
    //关键的一个就在于这里了,在前一篇讲applyMiddleware的时候介绍了这么做的意义,
    //实际就是把createStore这件事在applyMiddleware里面做,转移了锅。
    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
}

上面是第一个part,在校验完参数的正确之后,终于可以干点正事儿了。 createStore最终会返回一个Object,

{
 dispatch,
 subscribe,
 getState
}

接下来看看里面都做了什么:

getState

getState作用就是将当前state的状态返回回来,没啥好说的~

function getState() {
   return currentState
}

subscribe

作用:添加监听函数listener,它会在每次dispatch action的时候调用。

参数:listener(function): 在每一次dispatch action的时候都会调用的函数

返回:返回一个移除listener的函数

// 这个函数的作用就是,如果发现nextListeners,nextListeners指向同一个堆栈的话,就浅复制一份,这样改nextListeners就不会改到currentListeners
function ensureCanMutateNextListeners() {
    if (nextListeners === nextListeners) {
      nextListeners = currentListeners.slice()
    }
}

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

    let isSubscribed = true

    ensureCanMutateNextListeners()
    // 直接将监听的函数放进nextListeners里
    nextListeners.push(listener)

    return function unsubscribe() {
    // 如果已经移除了就直接返回
      if (!isSubscribed) {
        return
      }

      isSubscribed = false

      ensureCanMutateNextListeners()
      // 没有移除的话,先找到位置,通过splice移除
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }

在使用的时候就可以:

const unsubscribe = store.subscribe(() =>
  console.log(store.getState())
)

unsubscribe()

dispatch

dispatch 作为一个重点函数~ 其实它的作用就是触发状态的改变。

参数:action(object),它是一个描述发生了什么的对象,其中type是必须的属性。

返回:这个传入的object

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?'
      )
    }
    // 防止多次dispatch请求同时改状态,一定是前面的dispatch结束之后,才dispatch下一个
    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }

    try {
      isDispatching = true
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
    // 在dispatch的时候,又将nextListeners 赋值回currentListeners,
    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }

在上面一系列完成之后,需要初始化appState的状态。当INIT action被dispatched 的时候,每个reducer都会return回它的初始状态

dispatch({ type: ActionTypes.INIT })

参考资料: https://github.com/reactjs/redux/blob/master/src/createStore.js

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-11-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • INIT
  • createStore
    • getState
      • subscribe
        • dispatch
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档