Redux 是前端开发中常用的状态管理库,其简单易用的 API 和灵活的架构让许多前端开发者爱不释手。不过,除了使用外,我们还需要了解其源码实现,来更好地理解其设计思路和背后的原理。本文将从源码角度对 Redux 进行解读。
createStore
createStore 是 Redux 的一个核心函数,用于创建一个状态容器。下面是其源码:
-- -------------------- ---- -------
------ ------- -------- -------------------- --------------- --------- -
-- ------- -------------- --- ---------- -- ------ -------- --- ------------ -
-------- - --------------
-------------- - ---------
-
-- ------- -------- --- ------------ -
-- ------- -------- --- ----------- -
----- --- --------------- --- -------- -- -- - -----------
-
------ ------------------------------ ---------------
-
-- ------- ------- --- ----------- -
----- --- --------------- --- ------- -- -- - -----------
-
--- -------------- - -------
--- ------------ - --------------
--- ---------------- - --
--- ------------- - ----------------
--- ------------- - -----
-------- ------------------------------ -
-- -------------- --- ----------------- -
------------- - ------------------------
-
-
-------- ---------- -
-- --------------- -
----- --- ------
---- --- --- ---- ---------- ----- --- ------- -- ---------- - -
--- --- ---- -- ---- --- ------- ------ --- ---- -- ---- - ------ -------- -- ------------- - -
--- ---------- ------- --- ------- ------ ---- -- --------- ------- ----- ----- -- - -
-- ----------- ----- ------- -------- --- --- ----- ---- --- ------- -- -------- --------
-
-
------ ------------
-
-------- ------------------- -
-- ------- -------- --- ----------- -
----- --- --------------- -------- -- -- - -----------
-
--- ------------ - ----
------------------------------
----------------------------
------ -------- ------------- -
-- --------------- -
------
-
------------ - -----
------------------------------
----- ----- - -------------------------------
--------------------------- --
-
-
-------- ---------------- -
-- ------------------------ -
----- --- ------
-------- ---- -- ----- -------- - -
---- ------ ---------- --- ----- ---------
-
-
-- ------- ----------- --- ------------ -
----- --- ------
-------- --- --- ---- -- --------- ------ --------- - -
----- --- ---------- - ----------
-
-
-- --------------- -
----- --- --------------- --- --- -------- ----------
-
--- -
------------- - ----
------------ - ---------------------------- -------
- ------- -
------------- - -----
-
----- --------- - ----------------- - --------------
--- ---- - - -- - - ----------------- ---- -
----- -------- - ------------
----------
-
------ ------
-
-------- ---------------- -
----- --- ----------- ------ --- ---- -------- --- --- ------- ------ -------------------------------------------------------------------
-
---------- ----- ---------------- --
------ -
---------
----------
---------
---------------
-
-我们可以看到,createStore 整个函数有点长,但主要分为以下几个部分:
- 确定 preloadedState 和 enhancer 参数;
- 如果 enhancer 存在,则使用 enhancer 对 createStore 函数重新包装;
- 初始化 currentReducer、currentState、currentListeners 等各种状态;
- 定义 getState、subscribe、dispatch、replaceReducer 四个函数。
其中,getState 函数用于获取当前状态,subscribe 用于订阅状态变化,dispatch 用于发送一个 Action 并触发状态变化,replaceReducer 用于替换当前的 reducer。
combineReducers
combineReducers 用于将多个 Reducer 合并成一个。其主要实现思路是对每个 Reducer 接收到的 state 和 action 进行处理,并返回一个新的 state,最终将所有 Reducer 的 state 合并成一个对象。以下是其源码:
-- -------------------- ---- -------
------ ------- -------- ------------------------- -
----- ----------- - ---------------------
----- ------------- - --
--- ---- - - -- - - ------------------- ---- -
----- --- - --------------
-- ------- ------------- --- ----------- -
------------------ - -------------
-
-
----- ---------------- - --------------------------
------ -------- ----------------- - --- ------- -
--- ---------- - -----
----- --------- - --
--- ---- - - -- - - ------------------------ ---- -
----- --- - -------------------
----- ------- - ------------------
----- ------------------- - ----------
----- --------------- - ---------------------------- -------
-------------- - ---------------
---------- - ---------- -- --------------- --- -------------------
-
------ ---------- - --------- - -----
-
-可以看到,整个函数可分为四个部分:
- 将 Reducer 做一次过滤,去除不合法的
undefined、null、non-object; - 获取 Reducer 的 key,保存到
reducerKeys中; - 遍历
reducerKeys数组,对每一个 Reducer 进行处理,存储到finalReducers中; - 返回一个新的 Reducer,将所有最终处理出的 state 合并成一个对象。
applyMiddleware
applyMiddleware 用于应用中间件。其主要思路是通过柯里化来扩展 createStore 函数,使得其支持中间件的使用,可以记录日志、异步操作等。以下是其源码:
-- -------------------- ---- -------
------ ------- -------- ------------------------------- -
------ --------------------- -
------ ----------------- --------------- --------- -
----- ----- - -------------------- --------------- ---------
--- -------- - --------------
--- ----- - --
----- ------------- - -
--------- ---------------
--------- -------- -- ----------------
-
----- - -------------------------- -- --------------------------
-------- - ---------------------------------
------ -
---------
--------
-
-
-
-我们可以看到,整个函数有以下几个部分:
- 声明一个变量
middlewares,存储所有中间件; - 返回一个高阶函数,该函数接收一个
createStore函数,返回一个新的createStore; - 在新的
createStore中,声明一个存储所有中间件扩展函数的chain数组; - 定义
middlewareAPI对象,存储store.getState和最新的store.dispatch(因为后面会不断扩展); - 遍历所有中间件,将其执行,返回 Middlewares返回的是store对象的某个方法扩展函数,每个扩展函数都会接收到store.dispatch函数作为参数,返回一个新函数,接收一个action,执行扩展后的操作,并调用next函数(传入createStore到扩展函数返回的第一个函数),可以看到,最后通过compose 一次性将所有next合并成一个函数;
- 最后返回增强后的 store。该 store 中的
dispatch已经被执行了中间件扩展。
总结
Redux 的源码解读,让我们更深入地了解其设计思路和具体实现。虽然函数逻辑有点复杂,但核心思路还是比较简单的,可提高我们的代码设计能力和代码阅读能力。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/6497d0a148841e98944d69a2