一、实现目标
要实现一个带撤销功能的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中怎么实现一个撤销恢复的功能,关键点就是如何保存每一步操作,撤销或恢复时如何用保存的状态替换当前的状态。