使用 React 实现一个简单的待办事项列表
React 是现代前端开发中广泛使用的框架之一,擅长处理动态交互与状态管理。待办事项列表(To-Do List)作为一个经典的入门项目,能够全面展示 React 在组件管理、状态更新和事件处理方面的特点。本文将通过一个实际案例,介绍如何使用 React 实现一个简单的待办事项列表,支持添加、编辑和删除功能,并结合实现过程进行分析。
项目需求分析
待办事项列表的核心功能包括:
- 添加待办事项: 用户输入待办事项并提交后,新增一条记录。
- 编辑待办事项: 用户可以修改已有待办事项的内容。
- 删除待办事项: 用户可以移除不需要的待办事项。
- 列表展示: 按照添加顺序动态渲染待办事项。
额外的设计考虑:
- 用户交互体验: 支持编辑时的输入框切换和实时保存。
- 状态管理: 使用 React 的
useState管理待办事项列表和用户输入。
项目架构设计
我们将项目分为以下几个组件:
App组件: 主容器,管理全局状态并渲染子组件。ToDoList组件: 展示待办事项列表,支持删除和编辑。ToDoItem组件: 单个待办事项的表示与交互逻辑。AddToDo组件: 输入框和按钮,用于添加新的待办事项。
实现功能与逻辑分析
1. 初始化项目与状态管理
通过 React 的 useState 钩子管理待办事项列表和用户输入的状态。
const [todos, setTodos] = useState([]); // 用于存储待办事项的数组
const [newTodo, setNewTodo] = useState(""); // 用户输入的新待办事项
todos是存储待办事项的主状态,每次添加、编辑或删除都需要更新它。newTodo存储当前用户输入的新待办事项。
2. 添加待办事项
通过输入框和按钮,让用户能够添加新的待办事项。添加时:
- 验证用户输入是否为空。
- 使用
setTodos更新待办事项列表,添加一条记录。 - 清空输入框以提升用户体验。
逻辑:
const handleAddTodo = () => {
if (!newTodo.trim()) return; // 避免空输入
setTodos([...todos, { id: Date.now(), text: newTodo }]);
setNewTodo("");
};
3. 展示待办事项列表
通过 map 方法将 todos 状态渲染成动态列表,并在每个列表项上绑定删除和编辑功能。
逻辑:
{todos.map(todo => (
<ToDoItem
key={todo.id}
todo={todo}
onDelete={handleDeleteTodo}
onEdit={handleEditTodo}
/>
))}
4. 删除待办事项
删除待办事项需要通过 id 确定目标,并从 todos 中移除对应项。可以使用数组的 filter 方法实现。
逻辑:
const handleDeleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
5. 编辑待办事项
编辑功能通过切换输入框实现,用户在点击编辑按钮后可修改内容,并在失去焦点时保存。
逻辑:
const handleEditTodo = (id, newText) => {
setTodos(todos.map(todo => (todo.id === id ? { ...todo, text: newText } : todo)));
};
在 ToDoItem 组件中,可以使用 contentEditable 或 input 元素切换可编辑状态,并在 onBlur 或 Enter 键时触发保存。
完整的代码结构
以下是完整代码的模块化结构:
import React, { useState } from "react";
// 主容器组件
function App() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState("");
const handleAddTodo = () => { /* 添加逻辑 */ };
const handleDeleteTodo = (id) => { /* 删除逻辑 */ };
const handleEditTodo = (id, newText) => { /* 编辑逻辑 */ };
return (
<div>
<h1>待办事项列表</h1>
<AddToDo newTodo={newTodo} setNewTodo={setNewTodo} onAdd={handleAddTodo} />
<ToDoList todos={todos} onDelete={handleDeleteTodo} onEdit={handleEditTodo} />
</div>
);
}
// 添加待办事项组件
function AddToDo({ newTodo, setNewTodo, onAdd }) {
return (
<div>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="添加新的待办事项"
/>
<button onClick={onAdd}>添加</button>
</div>
);
}
// 待办事项列表组件
function ToDoList({ todos, onDelete, onEdit }) {
return (
<ul>
{todos.map(todo => (
<ToDoItem key={todo.id} todo={todo} onDelete={onDelete} onEdit={onEdit} />
))}
</ul>
);
}
// 单个待办事项组件
function ToDoItem({ todo, onDelete, onEdit }) {
const [isEditing, setIsEditing] = useState(false);
const [editText, setEditText] = useState(todo.text);
const handleSaveEdit = () => {
onEdit(todo.id, editText);
setIsEditing(false);
};
return (
<li>
{isEditing ? (
<input
type="text"
value={editText}
onChange={(e) => setEditText(e.target.value)}
onBlur={handleSaveEdit}
/>
) : (
<span onDoubleClick={() => setIsEditing(true)}>{todo.text}</span>
)}
<button onClick={() => onDelete(todo.id)}>删除</button>
</li>
);
}
export default App;
扩展功能与总结
通过这一示例,我们不仅实现了待办事项的基本功能,还能扩展更多功能,例如:
- 任务优先级: 为每个任务添加优先级标签,支持排序。
- 任务状态: 增加已完成/未完成的切换功能。
- 数据持久化: 使用
localStorage保存用户数据,刷新页面时保持列表。
React 的组件化设计让功能模块清晰分离,易于维护和扩展。通过这种方式,开发者可以快速构建用户友好的动态交互应用,同时掌握 React 的核心技能,为更复杂的项目奠定基础。