Redux 是一个非常流行的 JavaScript 应用程序状态管理库,它可以帮助开发者管理复杂的应用程序状态,使得应用程序状态管理更加简单和可维护。在 Redux 中,我们可以使用 createStore 方法来创建一个状态仓库,然后使用 applyMiddleware 方法来添加中间件,以便处理异步操作和其他一些高级用例。
本文将介绍 Redux 的 createStore 和 applyMiddleware 方法的源代码实现,并且会深入分析其内部实现和使用方式,以便开发者更好地理解Redux的工作原理并加强Web前端开发技能。
createStore 方法
createStore 方法是 Redux 库中创建状态仓库的函数。它的定义如下:
function createStore(reducer, preloadedState, enhancer) { // ... }
其中,reducer 是 Redux 应用的状态管理函数,用于定义应用程序状态的变化方式。preloadedState 是预加载的应用程序初始状态,可以是任何可以序列化的数据类型。enhancer 是可选的中间件增强器,用于增强 createStore 的功能。
createStore 方法内部实现
Redux 库中的 createStore 主要包括三个核心部分:store、dispatch 和 subscribe,下面分别进行详细介绍。
store
store 是保存应用程序状态的容器。它至少有以下方法:
- getState(): 返回当前状态值。
- dispatch(action): 触发状态更新。
- subscribe(listener): 注册一个监听器,当状态变化时会自动执行。
在 createStore 函数中,我们定义一个内部变量 state,用于存储状态值,以及一个数组 listeners,用于存储所有注册的监听器。代码如下:
function createStore(reducer, preloadedState, enhancer) { let state = preloadedState; const listeners = []; // ... }
dispatch
dispatch 方法是用来触发状态更新的函数,它接受一个 action 对象作为参数,如下所示:
function dispatch(action) { state = reducer(state, action); listeners.forEach(listener => listener()); }
在 dispatch 函数内部,我们首先调用 reducer 方法来计算新的状态值,然后执行所有注册的监听器,通知它们应用程序状态已经更新。
subscribe
subscribe 方法用来注册应用程序状态变化的监听器,它接收一个函数作为参数,函数会在状态变化时被调用。代码如下:
function subscribe(listener) { listeners.push(listener); return function unsubscribe() { const index = listeners.indexOf(listener); listeners.splice(index, 1); }; }
在 subscribe 方法中,我们先将监听器加入 listeners 数组,然后返回一个取消监听器的函数。当调用返回的函数时,它会从监听器数组中移除对应的监听器。
createStore 完整代码
下面是 createStore 方法的完整代码,包括状态容器 store、dispatch 和 subscribe 方法的定义。
-- -------------------- ---- ------- -------- -------------------- --------------- --------- - --- ----- - --------------- ----- --------- - --- -- ------- -------- --- ----------- - ------ ------------------------------ ---------------- - -------- ---------- - ------ ------ - -------- ---------------- - ----- - -------------- -------- -------------------------- -- ------------ - -------- ------------------- - ------------------------- ------ -------- ------------- - ----- ----- - ---------------------------- ----------------------- --- -- - ------------- ------ - --------- --------- ---------- -- -
applyMiddleware 方法
applyMiddleware 是 Redux 库中添加中间件的高级函数,它可以帮助开发者完成常见的复杂场景,如异步处理、路由处理等。它采用类似洋葱模型的方式,把多个中间件串联起来构成一个调用链。其定义如下:
-- -------------------- ---- ------- -------- ------------------------------- - ------ ----------- -- --------- --------------- -- - ----- ----- - -------------------- ---------------- --- -------- - --------------- ----- ------------- - - --------- --------------- --------- ------ -- ----------------- -- ----- ----- - -------------------------- -- --------------------------- -------- - ---------------------------------- ------ - --------- --------- -- -- -
applyMiddleware 函数的返回值是一个高阶函数,在接收 createStore 作为参数后,返回一个函数,这个函数接收 reducer 和 preloadedState 两个参数,并且返回一个包含 store 和 dispatch 的状态容器对象。
applyMiddleware 方法内部实现
applyMiddleware 函数的实现是基于 createStoe 方法的,它会使用传入的 createStore 方法来创建一个状态容器。
接下来,它定义一个名为 dispatch 的变量,并将其赋值为 store.dispatch,然后创建一个 middlewareAPI 对象,用于在各个中间件之间传递 getState 和 dispatch 函数。
同时,applyMiddleware 方法还会将所有中间件作为数组传入,通过 map 方法遍历数组,并且将 middlewareAPI 传入到各个中间件函数中,形成一个中间件的调用链。
最后,applyMiddleware 方法会调用 compose 函数来合并整个中间件调用链。其实现方式类似于管道,即先传入最右边的中间件,返回一个新的函数,接着再把当前函数传给左边的中间件,一直执行到最左边的中间件,最终返回一个新的函数用于替换 dispatch。
示例代码
下面是一个简单示例,我们将使用 Redux 和 applyMiddleware 函数来管理一个模拟的 TODO 列表应用程序。其中,包含两个自定义的中间件:logger 中间件和 async 中间件。
logger 中间件用于打印出状态更新前后的状态变化情况,代码如下:
const logger = store => next => action => { console.log('dispatching', action); const result = next(action); console.log('next state', store.getState()); return result; };
async 中间件用于处理异步操作,它会延迟一段时间后再执行 dispatch 函数,代码如下:
-- -------------------- ---- ------- ----- ----- - ----- -- ---- -- ------ -- - -- ------- ------ --- ----------- - ------ ------------- -- - ---------------------- ------------------ -- ------ - ------ ------------- --
下面是完整的示例代码:
-- -------------------- ---- ------- -------- ----------- - --- ------- - ------ ------------- - ---- ----------- ------ ---------- - ----- ------------ ---------- ----- --- ---- -------------- ------ ---------------- ------ -- ----- --- ------------ - - -------- ---------- --------------- - - ---- -- -------- ------ ------ - - -------- ---------------------- - ----------- ------- - ------ ------------- - ---- ------------------------ ------ -------------- -------- ------ ------ - - -------- ------------------------ - ------ ------ - --- ------- -- - ------ ---------------------------------------- ---- -- - -------------- - ------------------------- -------- ------ ---------- -- ---- -- - ----- ------- - ---------------- ------ ----------------- --- ----- ------ - ----- -- ---- -- ------ -- - -------------------------- -------- ----- ------ - ------------- ----------------- ------- ------------------ ------ ------- -- ----- ----- - ----- -- ---- -- ------ -- - -- ------- ------ --- ----------- - ------ ------------- -- - ---------------------- ------------------ -- ------ - ------ ------------- -- ----- ----- - ----------------------- ----------------------------- ------------------ -- - ---------------------------- ------------------ --- ---------------- ----- ----------- ----- ------ ------- --- ---------------- ----- -------------- ------ -- --- ---------------- ----- ------------------------ ------- ----------------- --- ------------------------- --------- -- - ------------- -- - ---------- ----- ----------- ----- ------ ------- --- -- ------ ---
在上面的示例代码中,我们首先定义了两个状态管理函数 todos 和 visibilityFilter,然后通过 combineReducer 函数将它们结合在一起,作为一个 rootReducer。接着我们定义了两个中间件 logger 和 async,用于处理状态更新的过程。
最后,我们通过 applyMiddleware 函数来增强 createStore 函数,这样可以在创建状态容器时自动应用中间件,并且使用返回的 store 对象来管理应用程序的状态更新。最终我们分别添加了几个 status action,来演示 store 的状态更新过程,最后输出了更新后的状态信息。
总结
Redux 是一个非常流行的 JavaScript 应用状态管理库,它可以帮助开发者管理复杂的应用程序状态。本文分别分析了其 createStore 和 applyMiddleware 方法的源代码实现,并且深入分析了其内部实现和使用方式,希望能够加强 Web 前端开发者的开发技能。同时,我们还演示了如何使用 Redux 和 applyMiddleware 函数来管理一个模拟的 TODO 列表应用程序,以便开发者更好地理解 Redux 的实现原理并加强实践能力。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64ffcc0595b1f8cacde15fd8