React 实现简单待办事项列表
待办事项列表是前端开发中常见的练习项目,既可以巩固 React 基础,又能帮助开发者理解状态管理、组件设计以及事件处理等重要概念。在这篇文章中,我们将一步步实现一个带有添加、编辑和删除功能的待办事项列表。
一、需求分析
一个功能完整的待办事项列表至少需要实现以下功能:
- 添加任务:允许用户输入任务并将其添加到列表。
- 编辑任务:支持修改已添加任务的内容。
- 删除任务:用户可以删除不需要的任务。
- 交互提示:实时更新列表内容,保持流畅的用户体验。
技术选型:选择 React 实现,利用其组件化和状态管理能力来组织代码。
二、功能分解
在实现时,需要将待办事项列表分解为以下核心模块:
- 任务输入框(TaskInput) :负责接受用户输入,并通过事件将任务传递给列表。
- 任务列表(TaskList) :负责显示所有任务,包含编辑和删除功能。
- 任务项(TaskItem) :独立处理每个任务的显示和交互。
- 主容器(App) :负责管理任务的整体状态(任务数组)并分发操作。
通过模块化设计,可以将代码拆分为小而明确的功能块,提高可维护性。
三、核心知识点解析
1. React 状态管理 React 的 useState 钩子是管理组件内状态的核心工具。这里,任务列表的所有状态会集中在 App 中,然后通过 Props 向下传递。
2. 数据流动 React 的单向数据流模式让任务状态的修改显得直观。任何更新操作都通过父组件提供的回调完成,并同步到子组件。
3. 事件处理 事件处理是待办事项列表的关键。通过监听表单输入、按钮点击等事件,我们可以动态地添加、修改和删除任务。
四、代码实现
以下是代码实现的分步解析。
1. 创建任务输入框组件
import React, { useState } from 'react';
function TaskInput({ onAddTask }) {
const [inputValue, setInputValue] = useState('');
const handleAdd = () => {
if (inputValue.trim()) {
onAddTask(inputValue);
setInputValue('');
}
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="输入待办事项"
/>
<button onClick={handleAdd}>添加</button>
</div>
);
}
export default TaskInput;
TaskInput 组件提供了一个输入框,用户可以输入任务。onAddTask 是一个父组件传递的回调函数,用于将新任务添加到列表中
2. 创建任务项组件
function TaskItem({ task, onEdit, onDelete }) {
const [isEditing, setIsEditing] = useState(false);
const [editValue, setEditValue] = useState(task.text);
const handleEdit = () => {
onEdit(task.id, editValue);
setIsEditing(false);
};
return (
<div>
{isEditing ? (
<>
<input
type="text"
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
/>
<button onClick={handleEdit}>保存</button>
</>
) : (
<>
<span>{task.text}</span>
<button onClick={() => setIsEditing(true)}>编辑</button>
</>
)}
<button onClick={() => onDelete(task.id)}>删除</button>
</div>
);
}
export default TaskItem;
TaskItem 负责显示单个任务内容。我们使用 isEditing 状态区分“查看”和“编辑”模式,允许用户修改任务。
3. 创建任务列表组件
function TaskList({ tasks, onEditTask, onDeleteTask }) {
return (
<div>
{tasks.map((task) => (
<TaskItem
key={task.id}
task={task}
onEdit={onEditTask}
onDelete={onDeleteTask}
/>
))}
</div>
);
}
export default TaskList;
TaskList 组件接受任务数组并将其映射为 TaskItem。父组件负责提供编辑和删除任务的逻辑。
4. 集成到主容器
import React, { useState } from 'react';
import TaskInput from './TaskInput';
import TaskList from './TaskList';
function App() {
const [tasks, setTasks] = useState([]);
const addTask = (text) => {
setTasks([...tasks, { id: Date.now(), text }]);
};
const editTask = (id, newText) => {
setTasks(
tasks.map((task) => (task.id === id ? { ...task, text: newText } : task))
);
};
const deleteTask = (id) => {
setTasks(tasks.filter((task) => task.id !== id));
};
return (
<div>
<h1>待办事项列表</h1>
<TaskInput onAddTask={addTask} />
<TaskList tasks={tasks} onEditTask={editTask} onDeleteTask={deleteTask} />
</div>
);
}
export default App;
App 是整个应用的状态中心。我们将任务数组的增删改操作封装成函数,并通过 Props 传递给子组件。
五、思考
1. 功能扩展性 虽然当前实现满足基础需求,但未来可以扩展为持久化存储(如 LocalStorage)或增加任务完成状态。
2. 数据结构设计 任务的 ID 使用 Date.now() 生成,在复杂应用中可以引入 UUID,以确保唯一性。
3. 用户体验 可以加入动画效果,如任务添加和删除时的过渡动效,提升视觉吸引力。
六、总结
通过分解需求、模块化设计和逐步实现,完成了一个简单但功能完善的待办事项列表。在这个过程中,不仅复习了 React 的基本能力,还思考了如何设计清晰的组件结构,提高代码的可扩展性和可维护性。这种实践模式对任何前端项目开发都有借鉴意义。