介绍
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 中间件:
import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' // import your root reducer here import rootReducer from './reducers' const store = createStore(rootReducer, applyMiddleware(thunk))
第二步:定义状态历史记录
在我们的例子中,保存历史记录的状态会类似于以下代码:
const initialState = { past: [], present: { // initial state }, future: [], }
在此例中,past 代表历史记录的过去,future 代表历史记录的未来,present 代表当前状态。
要实现撤销/重做操作,可以采用以下流程:
- 在每次页面加载时,初始化状态历史记录。
- 当发起一个 action 时,将当前状态保存到历史记录中。
- 当用户点击撤销或重做按钮时,所选方向的历史记录的最后一个条目成为当前状态。
第三步:定义 action creators 和 redux thunk
为了实现撤销/重做操作,可以在 action creators 中定义以下两个动作类型:
const UNDO = 'UNDO' const REDO = 'REDO'
这些动作类型允许在 action creators(即 undo 和 redo 函数)中调度一个 action,以便在 reducers 中更改过去、现在和未来。
要实现异步 action,您需要使用 redux-thunk 中间件和 redux-saga。
-- -------------------- ---- ------- ------ ----- ---- - -- -- -- ----- ---- -- ------ ----- ---- - -- -- -- ----- ---- -- ------ ----- ---------- - -- -- ---------- --------- -- - ----- - ----- -------- ------ - - ------------------ -- ------------- - ----- -------- - ---------------- - -- ----- ------- - ------------- ----------- - -- ---------- ----- ----- -------- - ----- -------- -------- --------- ------- --------- ---------- -- -- - - ------ ----- ---------- - -- -- ---------- --------- -- - ----- - ----- -------- ------ - - ------------------ -- --------------- - ----- ---- - --------- ----- --------- - --------------- ---------- ----- ----- -------- - ----- --------- --------- -------- ----- ------- --------- -- -- - -展开代码
然后,您需要将这些 action 添加到对应 reducer 中:
-- -------------------- ---- ------- ------ - ----- ---- - ---- ------------------ ----- -------------- - ------ - ------------- ------- -- - ------ ------------- - ---- ----- - -- ------ --- --------- --- -------- --- --- ------ ------ ----- - ---- ----- - -- ------ --- --------- --- -------- --- --- ------ ------ ----- - -- ------ ----- ------- -------- ------ ----- - - ------ ------- ----------------- -------- --------------- -- ----- -------- --展开代码
应该在这里完成撤销/重做的实现,使用上述代码作为起点即可轻松扩展您自己的 redux 应用程序来支持撤销/重做。
示例
接下来是一个示例,您可以在其中尝试实现撤销/重做功能。
-- -------------------- ---- ------- ------ ----- ---- ------- ------ -------- ---- ----------- ------ - --------- ------- - ---- ------------- ------ - ------------ ---------------- --------------- - ---- ------- ------ ----- ---- ------------- ------ --------- - ------------- - ---- ------------ ----- -------------- - ------ - -- ------- -- - ------ ------------- - ---- ------------ ------ ----- - - ---- ------------ ------ ----- - - -------- ------ ----- - - ----- ----------- - ----------------- -------- ------------------------ - ------- ---------------- --------- --------------- --------- --------------- --- -- ----- ------- - -- ------ ------------ ------------ ------- ------ -- -- - -- ---------------- ------- ---------------------------------------- ------- ---------------------------------------- ------- ------------------------------ ------- ------------------------------ --- - ----- -------- - ------- -- -- ------ ---------------------- -- ----- ----------- - - ------------ -- -- -- ----- ----------- --- ------------ -- -- -- ----- ----------- --- ------- -- -- -- ----- -------------- --- ------- -- -- -- ----- -------------- --- - ----- ---------------- - ----------------- --------------------- ----- ----- - ------------------------ ----------------------- ---------------- --------- -------------- ----------------- -- ------------ ------------------------------ -展开代码
我们定义了一个简单的计数器例子,它演示了如何在 redux 中应用撤销/重做功能。注意,我们使用了 redux-undo 库。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67ca8c16e46428fe9e2d09b2