详解 Redux 处理数据流、Action 和 Reducer

阅读时长 7 分钟读完

前言

Redux 是一个用于管理 JavaScript 应用程序状态的开源库。它基于 Flux 架构,提供了一个单向数据流的模式。Redux 的设计原则是单一的数据源,不可变的状态和纯函数。它是 React 生态系统中最受欢迎的状态容器之一。

在本篇文章中,我们将深入了解 Redux 的核心概念:数据流、Action 和 Reducer。我们会通过实例演示如何使用 Redux 处理应用程序中的数据流,并提供一些指导意义来帮助您更好地理解它的工作原理。

数据流

Redux 基于单向数据流的设计,在这种设计中,应用程序状态由一个全局的状态树管理。这个状态树是一个简单的 JavaScript 对象。当状态树中的状态发生变化时,Redux 会触发一个事件,通知应用程序进行相应的更新。

数据流中的主要角色有:Store、Action 和 Reducer。下面我们会重点讨论这些概念。

Store

Store 是应用程序状态的唯一来源。它包含了整个应用程序的状态树,并提供一种方便的接口用于访问和修改状态。每次修改状态时,Redux 都会生成一个新的状态树。

我们可以通过 createStore 函数来创建一个 Store。该函数接受一个 Reducer 作为参数,并返回一个 Store 对象。下面是一个简单的示例:

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

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

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

在上面的示例中,我们创建了一个 reducer 函数来处理状态变化。Reducer 是一个纯函数,它接受一个状态和一个 Action,并返回一个新的状态。我们将这个 reducer 函数传递给 createStore 函数,以创建一个新的 Store 实例。我们还将一个初始状态作为 createStore 函数的第二个参数传递。

Action

Action 是描述事件发生的对象。它是在应用程序中触发状态更改的路径之一。每次修改状态时,Redux 会生成一个新的状态树,这是通过 Action 触发的。

Action 是一个普通的 JavaScript 对象,必须有一个 type 字段来描述事件的类型。除此之外,Action 可以包含任意其他属性。下面是一个简单的 Action 示例:

上面的示例中,我们创建了一个 type 属性为 INCREMENT 的 Action。当这个 Action 被分派给 Store 后,Reducer 将根据 Action 的类型来更新状态。

Action 可以被任何其他函数、事件或组件触发。当应用程序状态发生变化时,Redux 会通知所有订阅 Store 的函数(称为“监听器”),以便它们可以更新应用程序界面。

Reducer

Reducer 是处理状态更新的函数。它是一个纯函数,它接受一个旧的状态和一个 Action,然后返回一个新的状态。Redcueer 函数的作用是根据 Action 的类型更新状态,并返回一个新的状态树。

作为函数,在 Reducer 内部不应对传入的参数进行修改。它应该总是返回新的状态对象,而不是修改原始的状态对象。

Reducer 的基本结构非常简单。它只需要使用 switch 语句来根据 Action 的类型更新状态。下面是一个简单的 Reducer 示例:

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

在这个简单的例子中,我们只有两个 Action 类型:INCREMENT 和 DECREMENT。根据 Action 类型,我们会返回一个新的状态对象来更新应用程序状态。

示例

了解了这些概念以后,我们来看一个完整的示例,以便更好的理解它们的用法。

在这个示例中,我们将创建一个包含两个按钮的计数器应用程序。当用户点击其中一个按钮时,我们将使用 Action 来触发更新。根据我们的 Reducer,我们会更新计数器的值。最后,我们会使用订阅 Store 的函数来更新我们的界面。

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

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

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

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

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

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

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

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

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

在上面的示例中,我们首先创建了一个简单的 Reducer 函数,以处理状态更新。接着,我们使用 createStore 函数创建了一个 Store 对象。

这里需要注意的是,我们在这里创建了一个全局的 Store,它可以在应用程序的任何部分中使用。在较大的应用程序中,更好的做法是将每个组件的状态存储在局部的 Store 中。但在本例中,全局 Store 显得更加简单和直观。

接下来,我们定义了 Counter 组件。当用户点击 + 或 - 按钮时,我们将使用 store.dispatch 函数来触发 Action,并更新应用程序状态。我们使用 store.getState 函数来获取当前状态,并将其显示在界面上。

最后,在 render 函数中,我们使用 ReactDOM.render 函数将 Counter 组件挂载到文档中。我们还调用了 store.subscribe 函数,以便我们可以在状态更改时更新界面。

指导意义

Redux 是开发 React 应用程序的首选状态容器之一。它为前端开发人员提供了一种可靠和可扩展的方式来管理应用程序状态。Redux 的设计原则是单一的数据源,不可变的状态和纯函数。这些原则确保了我们可以轻松地构建可靠的、高性能的应用程序。

在使用 Redux 时,请记住以下几点:

  1. 保持状态不可变。Redux 的关键设计原则之一是保持状态的不可变性。这意味着我们不能直接更改状态,而是应该创建一个新的状态对象。

  2. 尽量将状态保存在局部的 Store 中。在较大的应用程序中,全局状态树可能会变得庞大而复杂。对于这种情况,我们可以将每个组件的状态存储在局部的 Store 中,以便更好的管理状态。

  3. 将应用程序的状态划分为小的、逻辑相关的部分。这有助于使状态更加易于管理,同时还可以提高代码的可读性。

希望这篇文章能够帮助您更好的理解 Redux 的工作原理,并在开发应用程序时更好地利用它的功能。

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

纠错
反馈

纠错反馈