美文网首页
Redux源码阅读_1(上)

Redux源码阅读_1(上)

作者: 晴窗细语 | 来源:发表于2020-08-07 16:20 被阅读0次

    前言

    看完 Redux文档,对Redux的内部运作不是很了解,大致问题记录如下:

    • 容器组件怎么通过connect将store里的数据传入展示型组件的props中?
    • mapStateToProps与mapDispatchToProps怎么将state与dispatch的值组装到props?
    • action是什么?dispatch action做了些什么操作?
    • 若dispatch 一个函数,则函数默认参数有dispatch与state,自定义的函数怎么能默认接受这两个参数的?

    带着这些问题打开Redux源码,发现才一年的时间没做前端,Redux源码都从js换成ts了,屁颠屁颠跑去看TS文档,没咋看懂,但是应该能上源码了。

    源码结构

    首先看看文件夹目录结构


    src

    几个常用的api都在src/下,再下一级目录就是封装的一些类型,这些后面再详细描述,先开始上源码!

    index.ts

    这个文件主要导出了一些常用的接口

    import createStore from './createStore'
    import combineReducers from './combineReducers'
    import bindActionCreators from './bindActionCreators'
    import applyMiddleware from './applyMiddleware'
    import compose from './compose'
    import warning from './utils/warning'
    import __DO_NOT_USE__ActionTypes from './utils/actionTypes'
    
    //中间省略一些代码
    ···
    export {
      createStore,
      combineReducers,
      bindActionCreators,
      applyMiddleware,
      compose,
      __DO_NOT_USE__ActionTypes
    }
    
    

    可以看到我们Redux里常用的api,createstore、combineReducers、applyMiddleware、compose都给导出了,bindActionCreators之前没有用到过,正好可以看一下实现和用法。

    按照导出顺序挨个看看这些文件

    createStore.ts

    这个文件重载了两个createStore方法,主要区别是有无 preloadedState 这个参数。

    export default function createStore<
      S,
      A extends Action,
      Ext = {},
      StateExt = never
    >(
      reducer: Reducer<S, A>,
      enhancer?: StoreEnhancer<Ext, StateExt>
    ): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
    export default function createStore<
      S,
      A extends Action,
      Ext = {},
      StateExt = never
    >(
      reducer: Reducer<S, A>,
      preloadedState?: PreloadedState<S>,
      enhancer?: StoreEnhancer<Ext, StateExt>
    ): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
    

    用UML画了个假装是createStore的类图,主要是为了方便看这个函数里面定义的一些属性和方法。


    假装是createStore的类图

    函数申明

    export default function createStore<
      S,
      A extends Action,
      Ext = {},
      StateExt = never
    >(
      reducer: Reducer<S, A>,
      preloadedState?: PreloadedState<S> | StoreEnhancer<Ext, StateExt>,
      enhancer?: StoreEnhancer<Ext, StateExt>
    ): Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
    

    这个函数接收两到三个参数,其中,若只传入两个参数,且第二个参数为函数,会把第二个参数preloadedState赋值给enhancer,然后preloadedState赋值为undefined。

    if (
        (typeof preloadedState === 'function' && typeof enhancer === 'function') ||
        (typeof enhancer === 'function' && typeof arguments[3] === 'function')
      ) {
        throw new Error(
          'It looks like you are passing several store enhancers to ' +
            'createStore(). This is not supported. Instead, compose them ' +
            'together to a single function.'
        )
      }
    // 这里,其他都是类型检测
      if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
        enhancer = preloadedState as StoreEnhancer<Ext, StateExt>
        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 as PreloadedState<S>
        ) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
      }
    
      if (typeof reducer !== 'function') {
        throw new Error('Expected the reducer to be a function.')
      }
    
    

    然后就是方法内其他函数的介绍

    dispatch(action)

    该方法主要做了如下三个操作:
    1、修改 isDispatching的值(定义这个有点类似于锁的思想,阻止其他操作的修改)。
    2、计算属性currentState的值,该值通过getState()方法获取
    3、执行listeners[]数组里的每个listener方法。
    4、返回action(这个action为函数传入的action)

    代码如下:

    function dispatch(action: A) {
        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
        }
    
        const listeners = (currentListeners = nextListeners)
        for (let i = 0; i < listeners.length; i++) {
          const listener = listeners[i]
          listener()
        }
    
        return action
      }
    
    

    下接Redux源码阅读_1(下))

    相关文章

      网友评论

          本文标题:Redux源码阅读_1(上)

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