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

68 阅读4分钟

在现代前端开发中,React 是一个非常流行的 JavaScript 库,它通过组件化的方式来构建用户界面。在本篇文章中,我将通过一个简单的待办事项列表来展示如何使用 React 构建一个可交互的 Web 应用。该应用支持用户添加、编辑和删除待办事项。通过这个项目,我们不仅能够学习 React 的基础知识,还能对其组件化思想和状态管理有更深刻的理解。

1. 项目概述

待办事项列表是一个常见的应用,通常具有以下功能:

  • 添加任务:用户可以输入新的任务并将其添加到列表中。
  • 编辑任务:用户可以修改已经添加的任务内容。
  • 删除任务:用户可以删除不再需要的任务。
  • 标记任务完成:用户可以勾选完成的任务,使其从未完成状态转为已完成状态。

2. 技术栈

  • React:构建用户界面的核心库。
  • useState 和 useEffect Hooks:用于状态管理和副作用处理。
  • CSS:用于简单的样式布局。

3. 项目结构

我们将项目分成几个组件,每个组件负责不同的功能:

  • App:主组件,负责渲染待办事项列表。
  • TodoList:展示待办事项列表。
  • TodoItem:每个待办事项项,支持编辑、删除和标记完成。
  • AddTodo:用于输入并添加新任务。

4. 编码实现

4.1 创建主组件 App

首先,我们创建一个名为 App 的主组件,它将包含一个待办事项列表和一些操作。我们使用 useState 钩子来管理待办事项的状态,并将这个状态传递给子组件。

import React, { useState } from 'react';
import TodoList from './TodoList';
import AddTodo from './AddTodo';

const App = () => {
  const [todos, setTodos] = useState([]);
  
  const addTodo = (task) => {
    setTodos([...todos, { id: Date.now(), task, completed: false }]);
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  const editTodo = (id, newTask) => {
    setTodos(todos.map(todo => todo.id === id ? { ...todo, task: newTask } : todo));
  };

  const toggleCompletion = (id) => {
    setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo));
  };

  return (
    <div>
      <h1>待办事项列表</h1>
      <AddTodo addTodo={addTodo} />
      <TodoList
        todos={todos}
        deleteTodo={deleteTodo}
        editTodo={editTodo}
        toggleCompletion={toggleCompletion}
      />
    </div>
  );
};

export default App;

App 组件中,我们首先定义了一个 todos 状态,它是一个包含多个待办事项的数组。每个待办事项包含 id(唯一标识符)、task(任务内容)和 completed(是否完成)字段。我们还定义了四个函数:addTodo 用于添加任务,deleteTodo 用于删除任务,editTodo 用于编辑任务,toggleCompletion 用于切换任务的完成状态。

4.2 创建 AddTodo 组件

AddTodo 组件是一个表单,用户可以通过它输入新的任务。输入框的内容通过 useState 管理,用户点击添加按钮时,会将任务添加到 todos 数组中。

import React, { useState } from 'react';

const AddTodo = ({ addTodo }) => {
  const [task, setTask] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (task.trim()) {
      addTodo(task);
      setTask('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={task}
        onChange={(e) => setTask(e.target.value)}
        placeholder="输入新任务"
      />
      <button type="submit">添加任务</button>
    </form>
  );
};

export default AddTodo;

这个组件只有一个输入框和一个提交按钮。当用户在输入框中键入内容并提交时,handleSubmit 函数会调用 addTodo 函数,将新任务添加到列表中,并清空输入框。

4.3 创建 TodoList 组件

TodoList 组件负责渲染所有待办事项,并且将每个待办事项传递给 TodoItem 组件。它接收一个 todos 数组,并通过 map 方法将每个任务项渲染为一个 TodoItem

import React from 'react';
import TodoItem from './TodoItem';

const TodoList = ({ todos, deleteTodo, editTodo, toggleCompletion }) => {
  return (
    <ul>
      {todos.map(todo => (
        <TodoItem
          key={todo.id}
          todo={todo}
          deleteTodo={deleteTodo}
          editTodo={editTodo}
          toggleCompletion={toggleCompletion}
        />
      ))}
    </ul>
  );
};

export default TodoList;
4.4 创建 TodoItem 组件

TodoItem 组件负责展示单个待办事项的内容,并允许用户编辑、删除或标记为完成。

import React, { useState } from 'react';

const TodoItem = ({ todo, deleteTodo, editTodo, toggleCompletion }) => {
  const [isEditing, setIsEditing] = useState(false);
  const [newTask, setNewTask] = useState(todo.task);

  const handleEdit = () => {
    editTodo(todo.id, newTask);
    setIsEditing(false);
  };

  return (
    <li>
      {isEditing ? (
        <div>
          <input
            type="text"
            value={newTask}
            onChange={(e) => setNewTask(e.target.value)}
          />
          <button onClick={handleEdit}>保存</button>
        </div>
      ) : (
        <span
          style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
          onClick={() => toggleCompletion(todo.id)}
        >
          {todo.task}
        </span>
      )}
      <button onClick={() => deleteTodo(todo.id)}>删除</button>
      <button onClick={() => setIsEditing(!isEditing)}>编辑</button>
    </li>
  );
};

export default TodoItem;

在这个组件中,用户可以点击任务项来标记任务为完成(通过 toggleCompletion),也可以点击编辑按钮来修改任务内容。每个任务项都有一个删除按钮,用户点击后会触发删除操作。

5. 总结与思考

通过实现这个待办事项列表,我深入了解了 React 的组件化思想、状态管理以及组件之间的通信方式。在 React 中,每个组件都是独立的,它们之间通过 props 和 state 进行数据传递和管理,这种设计使得应用更加模块化,易于维护和扩展。

虽然 React 提供了许多功能和优化手段,但在开发过程中,我们还需要注意性能优化。比如,当待办事项数量增多时,如何高效渲染列表,避免不必要的重复渲染,可以通过使用 React.memouseMemo 来实现性能优化。