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

100 阅读3分钟

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

在前端开发中,待办事项列表(Todo List)是一个经典的入门项目。通过实现这个项目,我们可以很好地理解 React 的核心概念,如组件、状态管理、事件处理等。本文将详细介绍如何使用 React 实现一个具有添加、编辑和删除功能的待办事项列表。

项目需求分析

在开始编码之前,让我们先明确项目的具体需求:

  1. 用户可以添加新的待办事项
  2. 用户可以标记待办事项为已完成状态
  3. 用户可以编辑现有的待办事项
  4. 用户可以删除待办事项
  5. 所有待办事项需要持久化存储在本地

技术选型

本项目将使用以下技术栈:

  • React 18
  • TypeScript
  • CSS Module
  • localStorage 用于数据持久化

核心代码实现

首先,我们需要定义待办事项的接口:

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

然后,实现主要的 TodoList 组件:

import React, { useState, useEffect } from 'react';
import styles from './TodoList.module.css';

const TodoList: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [input, setInput] = useState('');
  const [editId, setEditId] = useState<number | null>(null);

  // 从 localStorage 加载数据
  useEffect(() => {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      setTodos(JSON.parse(savedTodos));
    }
  }, []);

  // 保存数据到 localStorage
  useEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos));
  }, [todos]);

  // 添加待办事项
  const handleAdd = () => {
    if (!input.trim()) return;
    
    const newTodo: Todo = {
      id: Date.now(),
      text: input,
      completed: false
    };
    
    setTodos([...todos, newTodo]);
    setInput('');
  };

  // 切换完成状态
  const toggleComplete = (id: number) => {
    setTodos(todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  // 删除待办事项
  const handleDelete = (id: number) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  // 编辑待办事项
  const handleEdit = (id: number, newText: string) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, text: newText } : todo
    ));
    setEditId(null);
  };

  return (
    <div className={styles.container}>
      <h1>待办事项列表</h1>
      
      <div className={styles.inputContainer}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="添加新的待办事项"
        />
        <button onClick={handleAdd}>添加</button>
      </div>

      <ul className={styles.todoList}>
        {todos.map(todo => (
          <li key={todo.id} className={`${styles.todoItem} ${todo.completed ? styles.completed : ''}`}>
            {editId === todo.id ? (
              <input
                type="text"
                value={todo.text}
                onChange={(e) => handleEdit(todo.id, e.target.value)}
                onBlur={() => setEditId(null)}
                autoFocus
              />
            ) : (
              <>
                <input
                  type="checkbox"
                  checked={todo.completed}
                  onChange={() => toggleComplete(todo.id)}
                />
                <span onDoubleClick={() => setEditId(todo.id)}>{todo.text}</span>
                <button onClick={() => handleDelete(todo.id)}>删除</button>
              </>
            )}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

为了让我们的待办事项列表看起来更加美观,我们还需要添加一些样式:

.container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.inputContainer {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.inputContainer input {
  flex: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.inputContainer button {
  padding: 8px 16px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.todoList {
  list-style: none;
  padding: 0;
}

.todoItem {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border-bottom: 1px solid #eee;
}

.completed span {
  text-decoration: line-through;
  color: #888;
}

实现要点解析

  1. 状态管理

    • 使用 useState 管理待办事项列表、输入框内容和编辑状态
    • 使用 useEffect 实现数据的持久化存储
  2. 功能实现

    • 添加:通过输入框和添加按钮实现
    • 编辑:双击文本触发编辑状态
    • 删除:点击删除按钮移除项目
    • 完成状态:通过复选框切换
  3. 数据持久化

    • 使用 localStorage 在页面刷新后保持数据
    • 每次数据更新时自动保存

性能优化考虑

  1. 使用 key 属性优化列表渲染
  2. 避免不必要的重渲染
  3. 使用防抖处理输入事件(可选优化)

项目扩展思考

  1. 添加分类功能
  2. 实现拖拽排序
  3. 添加截止日期
  4. 支持多用户
  5. 添加数据同步功能

总结

通过实现这个简单的待办事项列表,我们不仅掌握了 React 的基础知识,还学习了如何组织代码结构、管理状态以及处理用户交互。这个项目虽然简单,但包含了前端开发中的许多重要概念,是一个很好的学习案例。

在实际开发中,我们可能还需要考虑更多因素,比如:

  • 错误处理
  • 加载状态
  • 表单验证
  • 响应式设计
  • 无障碍访问

参考资源