美文网首页
读redux源码

读redux源码

作者: 南枫小谨 | 来源:发表于2021-07-26 14:01 被阅读0次

    准备工作

    redux 工作流程

    1. 首先由用户发出action store.dispatch(action)
    2. store 自动调用reducer 并传入两个参数当前 State 和收到的 Action,reducer 会返回新的state
    3. state有变化 store 会调用监听函数
      4.视图需设置监听函数store.subscribe(listener)
      5.listener可以通过store.getState()得到当前状态

    总结

    1. createStore 创建store
    2. reducer 初始化、修改状态函数(用户自己定义传入)
    3. getState 获取状态值
    4. dispatch 提交更新
    5. subscribe 变更订阅

    createStore

    以下为精简部分代码,感兴趣直接去github 上下载源码

    export default function createStore<
      S,
      A extends Action,
      Ext = {},
      StateExt = never
    >(
      reducer: Reducer<S, A>,
      enhancer?: StoreEnhancer<Ext, StateExt>
    // createStore  入参有两个 一个reducer 一个enhancer 用来使用中间件增强函数
    ):
    
     let currentState = preloadedState as S   //内部的state,用来存储数据
      let currentListeners: (() => void)[] | null = []   // 用来存放订阅回调的数组
    let nextListeners = currentListeners
    

    if (typeof enhancer !== 'undefined') { // 如果 enhancer 不为空 则返回一个增强的 createStore
    return enhancer(createStore)(
    reducer,
    preloadedState as PreloadedState<S>
    ) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
    }

     function getState(): S {
        // 返回 当前state 外部可以通过 store.getState()获取
        return currentState as S
      }
    
    function subscribe(listener: () => void){
         nextListeners.push(listener)   // 将callback 放入 监听数组,当state 发生改变的时候会遍历调用
            return function unsubscribe() {   // 同时返回一个取消订阅的函数
                   const index = nextListeners.indexOf(listener)
                   nextListeners.splice(index, 1)
                  currentListeners = null
        }
    }
    
    function dispatch(action: A) {
         currentState = currentReducer(currentState, action)  //   此处调用reducer 将state 传入
    // 调用绑定监听回调
        const listeners = (currentListeners = nextListeners)   
        for (let i = 0; i < listeners.length; i++) {
          const listener = listeners[i]
          listener()
        }
    
        return action
      }
    

    最后返回

    const store = {
        dispatch: dispatch as Dispatch<A>,
        subscribe,
        getState,
        replaceReducer,
        [$$observable]: observable
      } as unknown as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
      return store
    

    applyMiddleware

      const store = createStore(reducer, preloadedState)
     const middlewareAPI: MiddlewareAPI = {
            getState: store.getState,
            dispatch: (action, ...args) => dispatch(action, ...args)
          } // 将 控制权包装一下
          const chain = middlewares.map(middleware => middleware(middlewareAPI)) // 将控制权传给中间件
          dispatch = compose<typeof dispatch>(...chain)(store.dispatch) // 通过 compose 函数 将中间件串联起来
    
          return {
            ...store, 
            dispatch // 返回包装后的dispatch
          }
    
    

    compose 函数 用来组合各种中间件

    function compose(...funs){
        if(funs.length === 0){
            return (arg)=>arg
        }
        if(funs.length === 1){
            return funs[0]
        }
        return funs.reduce((a,b)=>(...args)=>a(b(...args)))
    }
    

    未完 待续

    相关文章

      网友评论

          本文标题:读redux源码

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