Redux 学习笔记(七):Redux 源码解读

阅读时长 11 分钟读完

Redux 是前端开发中常用的状态管理库,其简单易用的 API 和灵活的架构让许多前端开发者爱不释手。不过,除了使用外,我们还需要了解其源码实现,来更好地理解其设计思路和背后的原理。本文将从源码角度对 Redux 进行解读。

createStore

createStore 是 Redux 的一个核心函数,用于创建一个状态容器。下面是其源码:

-- -------------------- ---- -------
------ ------- -------- -------------------- --------------- --------- -
  -- ------- -------------- --- ---------- -- ------ -------- --- ------------ -
    -------- - --------------
    -------------- - ---------
  -

  -- ------- -------- --- ------------ -
    -- ------- -------- --- ----------- -
      ----- --- --------------- --- -------- -- -- - -----------
    -
    ------ ------------------------------ ---------------
  -

  -- ------- ------- --- ----------- -
    ----- --- --------------- --- ------- -- -- - -----------
  -

  --- -------------- - -------
  --- ------------ - --------------
  --- ---------------- - --
  --- ------------- - ----------------
  --- ------------- - -----

  -------- ------------------------------ -
    -- -------------- --- ----------------- -
      ------------- - ------------------------
    -
  -

  -------- ---------- -
    -- --------------- -
      ----- --- ------
        ---- --- --- ---- ---------- ----- --- ------- -- ---------- - -
          --- --- ---- -- ---- --- ------- ------ --- ---- -- ---- - ------ -------- -- ------------- - -
          --- ---------- ------- --- ------- ------ ---- -- --------- ------- ----- ----- -- - -
          -- ----------- ----- ------- -------- --- --- ----- ---- --- ------- -- -------- --------
      -
    -

    ------ ------------
  -

  -------- ------------------- -
    -- ------- -------- --- ----------- -
      ----- --- --------------- -------- -- -- - -----------
    -

    --- ------------ - ----

    ------------------------------
    ----------------------------

    ------ -------- ------------- -
      -- --------------- -
        ------
      -

      ------------ - -----

      ------------------------------
      ----- ----- - -------------------------------
      --------------------------- --
    -
  -

  -------- ---------------- -
    -- ------------------------ -
      ----- --- ------
        -------- ---- -- ----- -------- - -
          ---- ------ ---------- --- ----- ---------
      -
    -

    -- ------- ----------- --- ------------ -
      ----- --- ------
        -------- --- --- ---- -- --------- ------ --------- - -
          ----- --- ---------- - ----------
      -
    -

    -- --------------- -
      ----- --- --------------- --- --- -------- ----------
    -

    --- -
      ------------- - ----
      ------------ - ---------------------------- -------
    - ------- -
      ------------- - -----
    -

    ----- --------- - ----------------- - --------------
    --- ---- - - -- - - ----------------- ---- -
      ----- -------- - ------------
      ----------
    -

    ------ ------
  -

  -------- ---------------- -
    ----- --- ----------- ------ --- ---- -------- --- --- ------- ------ -------------------------------------------------------------------
  -

  ---------- ----- ---------------- --

  ------ -
    ---------
    ----------
    ---------
    ---------------
  -
-
展开代码

我们可以看到,createStore 整个函数有点长,但主要分为以下几个部分:

  1. 确定 preloadedState 和 enhancer 参数;
  2. 如果 enhancer 存在,则使用 enhancer 对 createStore 函数重新包装;
  3. 初始化 currentReducer、currentState、currentListeners 等各种状态;
  4. 定义 getState、subscribe、dispatch、replaceReducer 四个函数。

其中,getState 函数用于获取当前状态,subscribe 用于订阅状态变化,dispatch 用于发送一个 Action 并触发状态变化,replaceReducer 用于替换当前的 reducer。

combineReducers

combineReducers 用于将多个 Reducer 合并成一个。其主要实现思路是对每个 Reducer 接收到的 state 和 action 进行处理,并返回一个新的 state,最终将所有 Reducer 的 state 合并成一个对象。以下是其源码:

-- -------------------- ---- -------
------ ------- -------- ------------------------- -
  ----- ----------- - ---------------------
  ----- ------------- - --
  --- ---- - - -- - - ------------------- ---- -
    ----- --- - --------------

    -- ------- ------------- --- ----------- -
      ------------------ - -------------
    -
  -
  ----- ---------------- - --------------------------

  ------ -------- ----------------- - --- ------- -
    --- ---------- - -----
    ----- --------- - --
    --- ---- - - -- - - ------------------------ ---- -
      ----- --- - -------------------
      ----- ------- - ------------------
      ----- ------------------- - ----------
      ----- --------------- - ---------------------------- -------
      -------------- - ---------------
      ---------- - ---------- -- --------------- --- -------------------
    -
    ------ ---------- - --------- - -----
  -
-
展开代码

可以看到,整个函数可分为四个部分:

  1. 将 Reducer 做一次过滤,去除不合法的 undefinednullnon-object
  2. 获取 Reducer 的 key,保存到 reducerKeys 中;
  3. 遍历 reducerKeys 数组,对每一个 Reducer 进行处理,存储到 finalReducers 中;
  4. 返回一个新的 Reducer,将所有最终处理出的 state 合并成一个对象。

applyMiddleware

applyMiddleware 用于应用中间件。其主要思路是通过柯里化来扩展 createStore 函数,使得其支持中间件的使用,可以记录日志、异步操作等。以下是其源码:

-- -------------------- ---- -------
------ ------- -------- ------------------------------- -
  ------ --------------------- -
    ------ ----------------- --------------- --------- -
      ----- ----- - -------------------- --------------- ---------
      --- -------- - --------------
      --- ----- - --

      ----- ------------- - -
        --------- ---------------
        --------- -------- -- ----------------
      -
      ----- - -------------------------- -- --------------------------
      -------- - ---------------------------------

      ------ -
        ---------
        --------
      -
    -
  -
-
展开代码

我们可以看到,整个函数有以下几个部分:

  1. 声明一个变量 middlewares,存储所有中间件;
  2. 返回一个高阶函数,该函数接收一个 createStore 函数,返回一个新的 createStore;
  3. 在新的 createStore 中,声明一个存储所有中间件扩展函数的 chain数组;
  4. 定义 middlewareAPI 对象,存储 store.getState 和最新的 store.dispatch(因为后面会不断扩展);
  5. 遍历所有中间件,将其执行,返回 Middlewares返回的是store对象的某个方法扩展函数,每个扩展函数都会接收到store.dispatch函数作为参数,返回一个新函数,接收一个action,执行扩展后的操作,并调用next函数(传入createStore到扩展函数返回的第一个函数),可以看到,最后通过compose 一次性将所有next合并成一个函数;
  6. 最后返回增强后的 store。该 store 中的 dispatch 已经被执行了中间件扩展。

总结

Redux 的源码解读,让我们更深入地了解其设计思路和具体实现。虽然函数逻辑有点复杂,但核心思路还是比较简单的,可提高我们的代码设计能力和代码阅读能力。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6497d0a148841e98944d69a2

纠错
反馈

纠错反馈