使用 React 实现一个简单的待办事项列表 | 豆包MarsCode AI刷题

70 阅读4分钟

使用 React 实现一个简单的待办事项列表

React 是现代前端开发中广泛使用的框架之一,擅长处理动态交互与状态管理。待办事项列表(To-Do List)作为一个经典的入门项目,能够全面展示 React 在组件管理、状态更新和事件处理方面的特点。本文将通过一个实际案例,介绍如何使用 React 实现一个简单的待办事项列表,支持添加、编辑和删除功能,并结合实现过程进行分析。


项目需求分析

待办事项列表的核心功能包括:

  1. 添加待办事项: 用户输入待办事项并提交后,新增一条记录。
  2. 编辑待办事项: 用户可以修改已有待办事项的内容。
  3. 删除待办事项: 用户可以移除不需要的待办事项。
  4. 列表展示: 按照添加顺序动态渲染待办事项。

额外的设计考虑:

  • 用户交互体验: 支持编辑时的输入框切换和实时保存。
  • 状态管理: 使用 React 的 useState 管理待办事项列表和用户输入。

项目架构设计

我们将项目分为以下几个组件:

  1. App 组件: 主容器,管理全局状态并渲染子组件。
  2. ToDoList 组件: 展示待办事项列表,支持删除和编辑。
  3. ToDoItem 组件: 单个待办事项的表示与交互逻辑。
  4. AddToDo 组件: 输入框和按钮,用于添加新的待办事项。

实现功能与逻辑分析

1. 初始化项目与状态管理

通过 React 的 useState 钩子管理待办事项列表和用户输入的状态。

const [todos, setTodos] = useState([]); // 用于存储待办事项的数组
const [newTodo, setNewTodo] = useState(""); // 用户输入的新待办事项
  • todos 是存储待办事项的主状态,每次添加、编辑或删除都需要更新它。
  • newTodo 存储当前用户输入的新待办事项。

2. 添加待办事项

通过输入框和按钮,让用户能够添加新的待办事项。添加时:

  1. 验证用户输入是否为空。
  2. 使用 setTodos 更新待办事项列表,添加一条记录。
  3. 清空输入框以提升用户体验。

逻辑:

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 组件中,可以使用 contentEditableinput 元素切换可编辑状态,并在 onBlurEnter 键时触发保存。


完整的代码结构

以下是完整代码的模块化结构:

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 的核心技能,为更复杂的项目奠定基础。