Redux 技术解析及原理分析

阅读时长 13 分钟读完

前言

Redux 是一款流行的 JavaScript 状态管理工具,广泛应用于 React 等前端框架中。它提供了一种可预测化的数据流,让复杂的应用变得更易于理解、调试和维护。本文旨在深入探究 Redux 的技术原理,分析其设计理念与实现方式,以及如何应用 Redux 打造高效的前端应用。

Redux 的基本概念

Redux 采用了 Flux 架构的思想,将应用状态统一管理起来,避免了状态分散、难以追踪的问题。在 Redux 中,应用的状态保存在一个单一的全局对象上,称之为 Store。所有对应用状态的操作都通过派发 Action 的方式来实现,Action 是一个纯 JavaScript 对象,其中必须包含一个 type 属性,表示该操作的类型。

下面是一个示例 Action 的定义:

同时,Redux 定义了一个改变状态的函数 reducer,接收当前状态和 Action 两个参数,返回新的状态,其中 reducer 必须是一个纯函数,即不会有任何副作用,也不会改变输入的参数。这保证了 Redux 状态的可预测性和稳定性。

下面是一个简单的 reducer 示例:

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

在 Redux 中,所有对应用状态的操作都通过 Store 对象来进行,其中包含了以下几个核心方法:

  • createStore(reducer, [preloadedState], [enhancer]): 创建 Store 对象,并传入 reducer、初始状态和增强器函数。
  • store.dispatch(action): 派发 Action,改变应用状态。
  • store.getState(): 获取当前状态。
  • store.subscribe(listener): 注册监听,当状态改变时自动执行回调函数。

Redux 的原理分析

上面提到了 Redux 的基本概念,接下来我们将深入探究 Redux 的实现方法。

Store 的创建过程

在 Redux 中,通过 createStore 函数来创建 Store 对象。其调用方式为:

其中,reducer 是一个函数,接收当前状态和 Action 两个参数,返回新的状态;preloadedState 表示初始状态;enhancer 是 Store 增强器,可以用于增强 Store 功能。下面是 createStore 函数的实现:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

在 createStore 函数内部,首先判断传入的参数是否为函数,如果是,则说明传参方式为 createStore(reducer)(preloadedState),将 preloadedState 保存为 enhancer,reducer 保存在 reducer 变量中。

然后,创建了一些内部变量,并声明了一个 ensureCanMutateNextListeners 函数,用于保证 nextListeners 数组引用的可变性。这里的 nextListeners 用于保存下一个 action 对当前监听的 listener 执行之前的注册 listener 列表。

最后,将当前状态、当前 reducer 函数以及常用方法:dispatch, getState, subscribe,存入 store 对象中并返回,使用户可以通过 store.dispatch(action) 派发 action,使用 store.getState() 获取当前状态值,使用 store.subscribe(listener) 来监听 state 的变化并更新视图。

Action 的派发过程

在 Redux 内部,派发 action 调用的是 dispatch 函数,它接收一个 action 对象,进而判断 action.type 是否存在,如果不存在,直接抛出一个错误。同时,利用 reducer 函数完成 Store 状态的更新,然后通知所有的订阅者,执行他们提供的回调函数。派发过程中,还有一个 isDispatching 标志位,用于确保 reducer 函数的纯净性。

下面是 dispatch 函数的具体实现:

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

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

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

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

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

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

Reducer 的工作原理

在 Redux 的体系中,reducer 函数是一个很核心的概念,它被用来描述如何根据不同的 action 类型,更新应用的状态。根据 Flux 的思路,可以视其为一个单向的数据流,当前的状态在指定的 reducer 函数中被访问和修改,reducer 函数接受旧的状态和 Action 并返回新的状态。

因为 reducer 函数必须是纯函数,所以它不会改动原有的状态,而是返回新的对象代表了全新的状态。这也就确保了 Redux 的性质,注重简洁、稳定、可预测,从而能够更方便地应对更加复杂的应用。

下面是一个 reducer 函数的例子:

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

Redux 的应用

Redux 能帮助我们构建高效、可预测的前端应用,它提供了一种可预测化的数据流,方便进行状态管理。以下是一个 Redux 的例子,我们将通过此例解释如何使用 Redux。

首先,我们需要安装 Redux 库,可以通过以下命令完成安装:

接下来,我们考虑在 React 中使用 Redux,首先构建 Store 并在 Provider 中传入:

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

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

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

上面代码中,createStore 创建了 Store 对象,并传入了 rootReducer<Provider> 包装了整个应用,使其所有子组件都能够访问 Redux Store。

接下来,在 App.js 中使用 connect 函数将 React 组件和 Redux Store 进行绑定:

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

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

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

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

以上代码中,首先引入了组件内部需要操作的 incrementdecrement 两个函数以及 connect 函数。

connect 函数的第一个参数是将 state 映射到组件属性的函数 mapStateToProps, 将组件的 props 绑定到 Redux Store 中的状态 count 上。connect 函数的第二个参数是将修改 state 的函数绑定到 props 上,我们将 incrementdecrement 绑定到了 props 上。通过 connect 函数可以让组件拥有 countincrementdecrement 三个 props。

最后,我们需要编写 reducer 函数及相应的 action,下面是代码:

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

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

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

上面代码中,重新定义了 inititalState,通过 rootReducer 将传入的 action 对象与 state 绑定,通过 incrementdecrement 修改 count 值。最后将 incrementdecrement 需要的 action 两个函数作为对象输出。

至此,一个简单的包含计数器功能的示例应用就完成了。

总结

本文对 Redux 的应用进行了介绍,并对 Redux 的实现原理进行了分析。了解 Redux 是非常有益的,它不仅可以帮助我们构建更加复杂的应用程序,也可以提高我们对数据流的控制程度。相信这篇文章对读者有非常大的帮助。

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

纠错
反馈