Redux笔记

1,263 阅读2分钟

简介

Redux 是 JavaScript 应用的状态容器,提供可预测的状态管理。不与任意 UI 库绑定。

Redux Flow

流程图

redux读书笔记.jpg

Flow Gif

ReduxDataFlowDiagram-49fa8c3968371d9ef6f2a1486bd40a26.gif

核心 API 探索

核心 API List

@redux/src/index.ts

export {
  createStore, //创建根 Store;采用闭包创建了 dispatch 等函数操作闭包内的对象
  combineReducers, // 关联多个 reducer 一般用于大型应用的分区逻辑
  bindActionCreators,
  applyMiddleware, // 中间件逻辑
  compose, // 多个 fuc 串联执行的封装
  __DO_NOT_USE__ActionTypes
}

Redux.createStore

作用:创建根 Store;采用闭包创建了 dispatch 等函数操作闭包内的对象

核心代码:

/**
 * Creates a Redux store that holds the state tree.
 * The only way to change the data in the store is to call `dispatch()` on it.
 *
 * There should only be a single store in your app. To specify how different
 * parts of the state tree respond to actions, you may combine several reducers
 * into a single reducer function by using `combineReducers`.
 *
...
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

应用程序理论上只会使用一次createStore,剩余的所有操作均是对 createStore 拿到的 root store 做操作。

Store.dispatch

作用: 唯一一种改变 store 的方式

核心代码:

  function dispatch(action: A) {
    if (isDispatching) { // 如果正在 dispatch 则中断逻辑
      throw new Error('Reducers may not dispatch actions.')
    }

    try {
      isDispatching = true
      currentState = currentReducer(currentState, action) 
      // 调用 reducer 的方法根据 action 重新计算 state
    } finally {
      isDispatching = false
    }

    const listeners = (currentListeners = nextListeners) // 发送state更新的广播
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    return action
  }

Store.getState

作用:获取最新的 state 镜像

 /**
   * Reads the state tree managed by the store.
   *
   * @returns The current state tree of your application.
   */
  function getState(): S {
    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 as S
  }

Store.subscribe

作用: 注册 state 变更的监听。返回 unsubscribe 用于取消监听防止内存泄漏

  function subscribe(listener: () => void) {
    let isSubscribed = true

    ensureCanMutateNextListeners()
    nextListeners.push(listener)

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

      if (isDispatching) {
        throw new Error(
          'You may not unsubscribe from a store listener while the reducer is executing. ' +
            'See https://redux.js.org/api/store#subscribelistener for more details.'
        )
      }

      isSubscribed = false

      ensureCanMutateNextListeners()
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
      currentListeners = null
    }
  }

Redux.applyMiddleware

作用:redux 中间件,用于在 dispatch 方法执行前后进行切面操作

redux读书笔记-中间件模型.jpg 注意:中间的 dispatch 是 store.dispatch 没有经过任何中间件加强。

核心代码: @redux/

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)

@redux/src/compose.ts

接收一个 func 数组,从左到右连接。内部使用了 Array 的 reduce 方法进行收拢。

/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for the
 * resulting composite function.
 *
 * @param funcs The functions to compose.
 * @returns A function obtained by composing the argument functions from right
 *   to left. For example, `compose(f, g, h)` is identical to doing
 *   `(...args) => f(g(h(...args)))`.
 */
function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return <T>(arg: T) => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce(
    (a, b) =>
      (...args: any) =>
        a(b(...args))
  )
}

启发

  1. 代码中涉及到代码组合时考虑使用 componse 将函数进行组合方便后续扩展
  2. TODO

参考

  1. 官网 cn.redux.js.org/introductio…
  2. juejin.cn/post/684490…
  3. Coding-Guide