Redux 中如何实现 undo/redo

阅读时长 8 分钟读完

介绍

Redux 是一个流行的 JavaScript 应用程序状态管理工具。它是基于一种称为 Flux 的应用程序架构的实现,并被认为是构建可扩展 JavaScript 应用程序的一种最佳实践。其中一个主要功能是实现撤销/重做动作(undo/redo action)。本文将详细介绍如何在 Redux 中实现撤销/重做动作。

Redux 中的撤销/重做

在 Redux 中,撤销/重做操作可以通过保存应用程序状态历史记录来实现。即在每个操作(action)之后,将当前状态保存在状态历史记录中以供以后检索。当用户需要撤消操作时,可以简单地将它们导航回到之前的状态。

首先需要了解以下要点:

  • Redux store 可以通过 subscribe 方法响应状态(state)的变化
  • 在 applyMiddleware 中使用 thunk 或 redux-saga 进行异步操作
  • 了解如何使用 combineReducers 来组合状态 reducer

我们将会使用这些概念来实现撤销/重做操作的功能。

实现

第一步:Redux Store

创建 store 时,需要使用 applyMiddleware 函数包含 ReduxThunk 中间件:

第二步:定义状态历史记录

在我们的例子中,保存历史记录的状态会类似于以下代码:

在此例中,past 代表历史记录的过去,future 代表历史记录的未来,present 代表当前状态。

要实现撤销/重做操作,可以采用以下流程:

  • 在每次页面加载时,初始化状态历史记录。
  • 当发起一个 action 时,将当前状态保存到历史记录中。
  • 当用户点击撤销或重做按钮时,所选方向的历史记录的最后一个条目成为当前状态。

第三步:定义 action creators 和 redux thunk

为了实现撤销/重做操作,可以在 action creators 中定义以下两个动作类型:

这些动作类型允许在 action creators(即 undo 和 redo 函数)中调度一个 action,以便在 reducers 中更改过去、现在和未来。

要实现异步 action,您需要使用 redux-thunk 中间件和 redux-saga。

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

然后,您需要将这些 action 添加到对应 reducer 中:

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

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

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

应该在这里完成撤销/重做的实现,使用上述代码作为起点即可轻松扩展您自己的 redux 应用程序来支持撤销/重做。

示例

接下来是一个示例,您可以在其中尝试实现撤销/重做功能。

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

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

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

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

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

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

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

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

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

我们定义了一个简单的计数器例子,它演示了如何在 redux 中应用撤销/重做功能。注意,我们使用了 redux-undo 库。

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

纠错
反馈

纠错反馈