React 实现撤销、恢复功能


一、实现目标

要实现一个带撤销功能的todolist,需要以下完成以下步骤:

保存用户的每个操作;
针对每个操作设计与之对应的一个撤销逻辑;
实现撤销恢复的逻辑;

二、代码设计

1.状态管理

代码如下(示例):

reducer.js
import React from 'react'

export const TodoContext = React.createContext({})

export const initialState = {
  past: [],
  present: [],
  future: []
}

export const ReducerKey = {
  //添加
  ADD: 'ADD',
  //删除
  DEL: 'DEL',
  //撤销
  UNDO: 'UNDO',
  //恢复
  REDO: "REDO"
}

export default (state, action) => {
  const [type, value] = action
  const copy = JSON.parse(JSON.stringify(state))
  switch (type) {
    case ReducerKey.ADD:
      copy.past.push([...copy.present])
      copy.present.push(value)
      return {
        ...copy,
        future: []
      }
    case ReducerKey.DEL:
      copy.past.push([...copy.present])
      copy.present.splice(value, 1)
      return {
        ...copy,
        future: []
      }
    case ReducerKey.UNDO:
      let last = copy.past.pop()
      copy.future.unshift([...copy.present])
      return {
        ...copy,
        present: last,
      }
    case ReducerKey.REDO:
      let first = copy.future.shift()
      copy.past.push([...copy.present])
      return {
        ...copy,
        present: first,
      }
    default:
      return state;
  }
}

2.功能组件

代码如下(示例):

index.js
import React, { useReducer } from 'react'
import Input from './input'
import List from './list'
import reducer, { initialState, TodoContext, ReducerKey as Do } from './reducer'


export default () => {
  const [{ past, present, future }, dispatch] = useReducer(reducer, initialState)
  return (
    <div>
      <h2>list</h2>
      <p>Number:{present.length}</p>
      <div>
        <button onClick={() => dispatch([Do.UNDO])} disabled={past.length === 0}>撤销</button>
        <button onClick={() => dispatch([Do.REDO])} disabled={future.length === 0}>恢复</button>
      </div>
      <TodoContext.Provider value={{ state: { present }, dispatch }}>
        <Input />
        <List />
      </TodoContext.Provider>
    </div>
  )
}
input.js
import React, { useContext, useState } from 'react'
import { TodoContext, ReducerKey as Do } from './reducer'
export default  () => {
  const {dispatch} = useContext(TodoContext)
  const [value, setvalue] = useState('')
  return (
    <div>
      <input type="text" onBlur={(e) => setvalue(e.target.value)} />
      <button onClick={() => dispatch([Do.ADD, value])}>+</button>
    </div>
  )
}
list.js
import React, { useContext } from 'react'
import Todo from './todo'
import { TodoContext } from './reducer'

export default () => {
  const { state: { present } } = useContext(TodoContext)
  return (
    <ul>
      {
        present.map((item, index) => <Todo item={item} index={index} key={index} />)
      }
    </ul>
  )
}
todo.js
import React, { useContext } from 'react'
import { TodoContext, ReducerKey as Do } from './reducer'
export default  ({ index, item }) => {
  const {dispatch} = useContext(TodoContext)
  return (
    <li key={index}>
      <span>{index + 1}:{item}</span>
      <button onClick={() => dispatch([Do.DEL, index])}>-</button>
    </li>
  )
}

这样一个带有撤销恢复功能的todolist就完成了:
在这里插入图片描述


总结

以上就是今天要讲的内容,本文简单介绍了react中怎么实现一个撤销恢复的功能,关键点就是如何保存每一步操作,撤销或恢复时如何用保存的状态替换当前的状态。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值