前端实践选题: 使用React 实现一个简单的待办事项列表 | 豆包MarsCode Al刷题

103 阅读7分钟

这篇文章是我使用“AI练中学”的功能实现的一个简易的基于React的待办事项列表,包含基础的添加、编辑和删除功能。 接下来我会详细介绍实现的全部过程

一、React项目创建

1. 创建初始项目

在终端使用 npx create-react-app [项目名称] 命令创建项目,这是一个快速开始 React 项目的官方脚手架工具,它为我们提供了一个预配置的开发环境。

示例:

npx create-react-app react-demo

下载过程中,命令行会显示下载进度

image.png

项目下载完成后会提示‘secces’。此时,可以在文件夹目录下看到我们创建的react-demo文件夹。

image.png

点开react-demo文件夹,我们可以看到它的项目文件目录如下

image.png

注意:项目名称小写,不要出现中文

2. 进入项目文件夹,启动项目

(1)使用cd命令,进入项目文件夹

cd react-demo

image.png

(2)使用npm start启动项目

npm start

项目成功运行后,我们可以看到默认的React应用启动页面:

image.png

二、编写项目代码

1. 创建 TodoList.js 文件,并在 App.js 文件中引入

(1)在src目录下创建TodoList.js文件

image.png

(2)在App.js文件中引入TodoList.js

可以将App.js文件中不必要的代码删掉,只保留对TodoList组件的引用。

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

function App() {
  return (
    <div>
      <TodoList />
    </div>
  );
}

export default App;

2. 编写页面框架代码

TodoList.js中,编写一下项目基本的页面结构,包含标题,添加输入框及添加按钮,并且通过无序列表展示列表项内容,每一个列表项包含待办事项名称和编辑按钮,删除按钮。

function TodoList() {
    
    return (
        <div class="conatiner">
        <h1>待办事项列表</h1>
        {/* 添加新的todolist */}
        <div>
            <input type="text" placeholder="请输入待办事项" />
            <button class="addBtn">添加</button>
        </div>
        {/* 待办事项列表项项 */}
        <ul>
            <li class="list-child">
                <input type="text" value="list"/>
                <button class="editBtn">编辑</button>
                <button class="delBtn">删除</button>
            </li>
        </ul>
    </div>
    );
}

// 导出
export default TodoList;

页面展示效果如下:

image.png

3. 编写基本的css样式代码

(1)在src目录下创建创建TodoList.css文件

image.png

(2)编写样式代码

/* 设置整个容器 */
.container {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #f9f9f9;
    border: 1px solid #ddd;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

/* 标题的样式 */
h1 {
    font-size: 24px;
    color: #333;
    text-align: center;
    margin-bottom: 20px;
}


.input-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

/* 输入框样式 */
input[type="text"] {
    flex-grow: 1;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    margin-right: 10px;
    font-size: 16px;
}

/* 添加按钮 */
.addBtn {
    padding: 10px 20px;
    background-color: #5cb85c;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
    transition: background-color 0.3s ease;
}

.addBtn:hover {
    background-color: #4cae4c;
}

/* 无序列表的样式 */
ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

/* 设置每个列表项的样式 */
.list-child {
    display: flex;
    align-items: center;
    padding: 10px;
    border-bottom: 1px solid #eee;
    transition: background-color 0.3s ease;
}

.list-child:last-child {
    border-bottom: none;
}

.list-child input[type="checkbox"] {
    margin-right: 10px;
}

.list-child span {
    flex-grow: 1;
    margin-right: 10px;
    color: #333;
}

.list-child button {
    padding: 5px 10px;
    background-color: #f0ad4e;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;
}

.list-child button:hover {
    background-color: #ec971f;
}

.list-child button.delBtn {
    margin-right: 10px;
}

.list-child button.editBtn {
    background-color: #5bc0de;
}

.list-child button.editBtn:hover {
    background-color: #46b8da;
}

(3)在TodoList.js文件中引入css文件

import './TodoList.css'; // 导入CSS文件

(4)在页面中通过className应用样式

return (
    <div className="container">
        <h1>待办事项列表</h1>
        {/* 添加新的待办事项 */}
        <div className="input-container">
            <input
                type="text"
                placeholder="请输入待办事项" />
            <button className="addBtn" >添加</button>
        </div>
        {/* 待办事项列表项 */}
        <ul>
            <li className="list-child"> 
                <input type="text" />
                <button className="editBtn" >编辑</button>
                <button className="delBtn" >删除</button>
            </li>
        </ul>
    </div>
};

4. 编写基本功能逻辑

(1)引入ReactuseState钩子

首先,我们需要从React库中引入useState钩子,这是一个用于在函数组件中添加状态的Hook。

import React, { useState } from 'react';

(2)初始化待办事项状态

接下来,我们使用useState钩子来创建一个名为todos的状态变量,这个变量将用来存储所有的待办事项。同时,我们创建一个名为setTodos的函数,用来更新todos数组

const [todos, setTodos] = useState([]); // 使用useState钩子初始化待办事项数组和设置函数

这里,todos是一个空数组,初始时不包含任何待办事项。setTodos是一个函数,当调用它并传入一个新的数组时,它会更新todos的状态,从而触发组件的重新渲染。

(3)添加待办事项

  • 初始化输入框状态
const [input, setInput] = useState(''); // 输入框的值和设置函数
  • 编写添加函数

为了添加新的待办事项,我们定义一个名为handleAddTodo的函数。这个函数首先检查输入是否为空,如果不为空,则创建一个新的待办事项对象,并将其添加到todos数组中。

其中editing为是否可编辑的状态,方便后续编辑功能的实现

// 添加待办事项功能
const handleAddTodo = () => {
    if (input.trim() !== '') {
        setTodos([...todos, { id: todos.length + 1, text: input, editing: false }]);
        setInput(''); // 清空输入框
    }
};
  • input输入框中绑定状态
<input
    type="text"
    // 绑定状态获取输入值
    value={input}
    // 添加onChange事件来更新状态
    onChange={(e) => setInput(e.target.value)}
    placeholder="请输入待办事项" />
  • todos渲染列表
 <ul>
    {/* 用todos渲染列表 */}
    {todos.map((todo) => (
        <li key={todo.id} className="list-child"> {/* 确保每个列表项有唯一的key */}
            <span >
                {todo.text}
            </span>
            <button className="editBtn" >编辑</button>
            <button className="delBtn" >删除</button>
        </li>
    ))}
</ul>
  • 为添加按钮绑定点击onclick逻辑
<button className="addBtn" onClick={handleAddTodo} >添加</button>

(4)编辑待办事项

  • input框绑定状态,动态绑定diabled属性,只有在编辑状态时才允许编辑
<input
    type="text"
    value={todo.text}
    onChange={(e) => handleEditTodo(todo.id, e.target.value)}
    onBlur={() => handleEditTodo(todo.id, todo.text)}
    // 控制输入框是否禁用,只有在编辑状态时才允许编辑
    disabled={!todo.editing}
/>
  • 编写进入编辑模式的函数,控制输入框是否可编辑,
// 进入编辑模式
const handleEditClick = (id) => {
    setTodos(todos.map((todo) => {
        if (todo.id === id) {
            return { ...todo, editing: true }; // 点击编辑按钮时设为true
        }
        return todo;
    }));
};
  • 编写编辑事项列表的函数
// 编辑待办事项功能
const handleEditTodo = (id, newText) => {
    setTodos(todos.map((todo) => {
        if (todo.id === id) {
            return { ...todo, text: newText, editing: false }; // 编辑后退出编辑状态
        }
        return todo;
    }));
};
  • 为编辑按钮绑定点击onclick逻辑
<button className="editBtn" onClick={() => handleEditClick(todo.id)}>编辑</button>

(5)删除待办事项

  • 编写删除事项列表的函数
// 删除待办事项功能
const handleDeleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
};
  • 为删除按钮绑定点击onclick逻辑
<button className="delBtn" onClick={() => handleDeleteTodo(todo.id)}>删除</button>

三、完整代码及页面展示

1. App.js

略,该部分代码与前面的app.js代码内容一致

2.TodoList.js

import React, { useState } from 'react';
import './TodoList.css'; // 导入CSS文件

function TodoList() {
    const [todos, setTodos] = useState([]); // 使用useState钩子初始化待办事项数组和设置函数
    const [input, setInput] = useState(''); // 输入框的值和设置函数

    // 添加待办事项功能
    const handleAddTodo = () => {
        if (input.trim() !== '') {
            setTodos([...todos, { id: todos.length + 1, text: input, editing: false }]);
            setInput(''); // 清空输入框
        }
    };

    // 进入编辑模式
    const handleEditClick = (id) => {
        setTodos(todos.map((todo) => {
            if (todo.id === id) {
                return { ...todo, editing: true }; // 点击编辑按钮时设为true
            }
            return todo;
        }));
    };

    // 编辑待办事项功能
    const handleEditTodo = (id, newText) => {
        setTodos(todos.map((todo) => {
            if (todo.id === id) {
                return { ...todo, text: newText, editing: false }; // 编辑后退出编辑状态
            }
            return todo;
        }));
    };

    // 删除待办事项功能
    const handleDeleteTodo = (id) => {
        setTodos(todos.filter(todo => todo.id !== id));
    };

    return (
        <div className="container">
            <h1>待办事项列表</h1>
            {/* 添加新的待办事项 */}
            <div className="input-container">
                <input
                    type="text"
                    // 绑定状态获取输入值
                    value={input}
                    // 添加onChange事件来更新状态
                    onChange={(e) => setInput(e.target.value)}
                    placeholder="请输入待办事项" />
                <button className="addBtn" onClick={handleAddTodo} >添加</button>
            </div>
            {/* 待办事项列表项 */}
            <ul>
                {/* 用todos渲染列表 */}
                {todos.map((todo) => (
                    <li key={todo.id} className="list-child"> {/* 确保每个列表项有唯一的key */}
                        <input
                            type="text"
                            value={todo.text}
                            onChange={(e) => handleEditTodo(todo.id, e.target.value)}
                            onBlur={() => handleEditTodo(todo.id, todo.text)}
                            // 控制输入框是否禁用,只有在编辑状态时才允许编辑
                            disabled={!todo.editing}
                        />
                        <button className="editBtn" onClick={() => handleEditClick(todo.id)}>编辑</button>
                        <button className="delBtn" onClick={() => handleDeleteTodo(todo.id)}>删除</button>
                    </li>
                ))}
            </ul>
        </div>
    );
}

// 导出
export default TodoList;

3.TodoList.css

略,该部分代码与前面的样式代码内容一致

4.页面展示

image.png

# 个人思考与分析

这篇笔记是为了记录本人在学习了react课程之后的一些练习和实战,在编写项目的过程中,我更深入的了解了如何使用react,但因为是第一次使用react,在各方面都很不熟练,需要不断的学习,以后我也会更进一步的去学习如何使用react,更好的掌握react,编写更优秀的项目。

最后,如果本文有哪里写的不对的地方欢迎大家批评指正,非常感谢!