使用React和Material-UI构建TODO应用的前端UI

使用React和Material-UI构建TODO应用的前端UI

        • 引言
        • 环境准备
        • 代码解析
          • 1. 导入必要的模块
          • 2. 创建React组件
          • 3. 定义函数
            • 3.1 获取TODO列表
            • 3.2 创建TODO项
            • 3.3 更新TODO项
            • 3.4 删除TODO项
            • 3.5 处理编辑点击事件
            • 3.6 关闭编辑对话框
            • 3.7 保存编辑内容
          • 4. 使用Effect钩子
          • 5. 渲染组件
        • 功能实现
        • 优化建议
        • 总结

引言

在现代Web开发中,TODO列表应用是一个经典的示例,用于展示如何使用前端技术构建一个简单的任务管理工具。本文将详细介绍如何使用React框架和Material-UI库来构建一个TODO列表应用,并解释代码的各个部分,帮助读者理解其工作原理。

后端API请参考,使用Express.js和SQLite3构建简单TODO应用的后端API

环境准备

在开始之前,请确保你已经安装了以下工具和库:

  1. Node.js:确保你已经安装了Node.js,可以从Node.js官网下载并安装。
  2. npm:Node.js的包管理工具,随Node.js一起安装。
  3. React:一个用于构建用户界面的JavaScript库,可以通过npm安装。
  4. Material-UI:一个基于Material Design的React组件库,同样可以通过npm安装。
  5. axios:一个基于Promise的HTTP客户端,用于处理API请求。

安装所需的依赖:

npm install react @mui/material @emotion/react @emotion/styled axios
代码解析

让我们逐步分析代码,理解每个部分的功能。

1. 导入必要的模块
import { useState, useEffect } from 'react';
import axios from 'axios';
import {TextField,Button,Checkbox,List,ListItem,ListItemText,IconButton,Dialog,DialogTitle,DialogContent,DialogActions,FormControlLabel
} from '@mui/material';
import { Delete, Edit } from '@mui/icons-material';
import { Todo } from '../types/todo';
  • React:导入useStateuseEffect钩子,用于状态管理和副作用处理。
  • axios:用于发送HTTP请求。
  • Material-UI:导入各种组件,如文本框、按钮、列表、对话框等。
  • Icons:导入删除和编辑图标。
  • Todo类型:定义TODO项的类型,确保数据的类型安全。
2. 创建React组件
export default function TodoList() {const [todos, setTodos] = useState<Todo[]>([]);const [searchTerm, setSearchTerm] = useState('');const [newTodo, setNewTodo] = useState({ title: '', description: '' });const [editingTodo, setEditingTodo] = useState<Todo | null>(null);const [editForm, setEditForm] = useState({ title: '', description: '', completed: false });
  • todos:存储TODO列表的状态。
  • searchTerm:存储搜索词的状态。
  • newTodo:存储新TODO项的状态。
  • editingTodo:存储正在编辑的TODO项的状态。
  • editForm:存储编辑表单的状态。
3. 定义函数
3.1 获取TODO列表
const fetchTodos = async () => {try {const response = await axios.get(`http://localhost:3002/api/todos?q=${searchTerm}`);setTodos(response.data);} catch (error) {console.error('Error fetching todos:', error);}
};
  • 功能:从后端获取TODO列表,支持搜索功能。
  • 实现:使用axios.get发送GET请求,根据searchTerm进行模糊搜索。
3.2 创建TODO项
const createTodo = async () => {if (!newTodo.title.trim()) return;try {await axios.post('http://localhost:3002/api/todos', newTodo);setNewTodo({ title: '', description: '' });fetchTodos();} catch (error) {console.error('Error creating todo:', error);}
};
  • 功能:创建一个新的TODO项。
  • 实现:检查标题是否为空,使用axios.post发送POST请求,创建成功后清空表单并刷新列表。
3.3 更新TODO项
const updateTodo = async (todo: Todo, isToggleComplete = false) => {try {const updatedTodo = isToggleComplete? { ...todo, completed: !todo.completed }: { ...todo, title: editForm.title, description: editForm.description, completed: editForm.completed };await axios.put(`http://localhost:3002/api/todos/${todo.id}`, updatedTodo);setEditingTodo(null);fetchTodos();} catch (error) {console.error('Error updating todo:', error);}
};
  • 功能:更新TODO项,支持标记完成和编辑内容。
  • 实现:根据isToggleComplete决定是更新完成状态还是编辑内容,使用axios.put发送PUT请求。
3.4 删除TODO项
const deleteTodo = async (id: number) => {try {await axios.delete(`http://localhost:3002/api/todos/${id}`);fetchTodos();} catch (error) {console.error('Error deleting todo:', error);}
};
  • 功能:删除指定的TODO项。
  • 实现:使用axios.delete发送DELETE请求,删除成功后刷新列表。
3.5 处理编辑点击事件
const handleEditClick = (todo: Todo) => {setEditingTodo(todo);setEditForm({title: todo.title,description: todo.description || '',completed: todo.completed});
};
  • 功能:打开编辑对话框,填充TODO项的详细信息。
  • 实现:设置editingTodoeditForm状态,显示编辑表单。
3.6 关闭编辑对话框
const handleClose = () => {setEditingTodo(null);setEditForm({ title: '', description: '', completed: false });
};
  • 功能:关闭编辑对话框,重置表单。
  • 实现:清除editingTodoeditForm状态。
3.7 保存编辑内容
const handleSave = () => {if (editingTodo && editForm.title.trim()) {updateTodo(editingTodo);}
};
  • 功能:保存编辑的内容。
  • 实现:检查标题是否为空,调用updateTodo更新TODO项。
4. 使用Effect钩子
useEffect(() => {const debounceSearch = setTimeout(() => {fetchTodos();}, 300);return () => clearTimeout(debounceSearch);
}, [searchTerm]);
  • 功能:实现搜索的防抖动效果,防止频繁请求。
  • 实现:使用setTimeout延迟300毫秒后执行fetchTodos,并在组件销毁时清除定时器。
5. 渲染组件
return (<div style={{ maxWidth: 600, margin: '0 auto', padding: '20px' }}><TextFieldfullWidthlabel="Search Todos"variant="outlined"value={searchTerm}onChange={(e) => setSearchTerm(e.target.value)}margin="normal"/><List>{todos.map((todo) => (<ListItemkey={todo.id}secondaryAction={(<><IconButton onClick={() => handleEditClick(todo)}><Edit /></IconButton><IconButton onClick={() => deleteTodo(todo.id)}><Delete /></IconButton></>)}style={{display: todo.completed ? 'none' : 'flex',opacity: todo.completed ? 0.7 : 1}}><Checkboxchecked={Boolean(todo.completed)}onChange={() => updateTodo(todo, true)}/><ListItemTextprimary={todo.title}secondary={todo.description}style={{textDecoration: todo.completed ? 'line-through' : 'none',}}/></ListItem>))}</List><div style={{ display: 'flex', gap: 10, marginBottom: 20 }}><TextFieldfullWidthlabel="New Todo Title"value={newTodo.title}onChange={(e) => setNewTodo({ ...newTodo, title: e.target.value })}/><TextFieldfullWidthlabel="Description"value={newTodo.description}onChange={(e) => setNewTodo({ ...newTodo, description: e.target.value })}/><Buttonvariant="contained"color="primary"onClick={createTodo}>Add</Button></div><Dialog open={Boolean(editingTodo)} onClose={handleClose}><DialogTitle>Edit Todo</DialogTitle><DialogContent><TextFieldautoFocusmargin="dense"label="Title"fullWidthvalue={editForm.title}onChange={(e) => setEditForm({ ...editForm, title: e.target.value })}/><TextFieldmargin="dense"label="Description"fullWidthmultilinerows={3}value={editForm.description}onChange={(e) => setEditForm({ ...editForm, description: e.target.value })}/><FormControlLabelcontrol={(<Checkboxchecked={editForm.completed}onChange={(e) => setEditForm({ ...editForm, completed: e.target.checked })}/>)}label="Completed"/></DialogContent><DialogActions><Button onClick={handleClose} color="primary">Cancel</Button><ButtononClick={handleSave}color="primary"disabled={!editForm.title.trim()}>Save</Button></DialogActions></Dialog></div>
);
  • 搜索框:允许用户输入搜索词,实时搜索TODO列表。
  • TODO列表:显示所有TODO项,每个项包含标题、描述、编辑和删除按钮,以及完成状态Checkbox。
  • 添加TODO表单:允许用户输入新TODO的标题和描述,点击“Add”按钮创建。
  • 编辑对话框:当用户点击编辑按钮时,显示编辑表单,允许修改TODO的标题、描述和完成状态。
功能实现
  1. 添加TODO项:用户输入标题和描述后,点击“Add”按钮,发送POST请求到后端,创建新的TODO项。
  2. 编辑TODO项:用户点击编辑按钮,打开编辑对话框,修改TODO项的详细信息后,点击“Save”按钮,发送PUT请求到后端,更新TODO项。
  3. 删除TODO项:用户点击删除按钮,发送DELETE请求到后端,删除指定的TODO项。
  4. 搜索TODO项:用户输入搜索词,组件会自动搜索标题或描述中包含该词的TODO项,支持防抖动功能,减少请求次数。
  5. 标记完成:用户点击Checkbox,TODO项会被标记为完成,样式会变为灰色并添加删除线。
优化建议

尽管这段代码已经可以正常工作,但为了提升应用的性能和用户体验,可以考虑以下优化:

  1. 添加加载状态:在数据加载过程中,显示加载动画,提升用户体验。
  2. 添加错误提示:在请求失败时,显示错误提示信息,帮助用户了解问题所在。
  3. 添加成功提示:在创建、更新或删除TODO项成功后,显示成功提示信息。
  4. 优化样式:根据Material Design规范,优化组件的样式和布局,提升视觉效果。
  5. 添加响应式设计:确保应用在不同设备上都能良好显示,提升应用的适应性。
  6. 添加数据验证:在前端和后端都添加数据验证,确保输入的数据合法有效。
总结

通过本文,我们详细解析了一个使用React和Material-UI构建的TODO列表应用。从状态管理、HTTP请求到组件渲染,每个部分都进行了详细的解释。希望这篇文章能够帮助读者理解如何使用这些技术构建一个简单的TODO应用,并为进一步的学习和开发打下基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/11973.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四、GPIO中断实现按键功能

4.1 GPIO简介 输入输出&#xff08;I/O&#xff09;是一个非常重要的概念。I/O泛指所有类型的输入输出端口&#xff0c;包括单向的端口如逻辑门电路的输入输出管脚和双向的GPIO端口。而GPIO&#xff08;General-Purpose Input/Output&#xff09;则是一个常见的术语&#xff0c…

分析哲学:从 语言解剖到 思想澄清的哲学探险

分析哲学&#xff1a;从 语言解剖 到 思想澄清 的哲学探险 第一节&#xff1a;分析哲学的基本概念与公式解释 【通俗讲解&#xff0c;打比方来讲解&#xff01;】 分析哲学&#xff0c;就像一位 “语言侦探”&#xff0c;专注于 “解剖语言”&#xff0c;揭示我们日常使用的语…

XCCL、NCCL、HCCL通信库

XCCL提供的基本能力 XCCL提供的基本能力 不同的XCCL 针对不同的网络拓扑&#xff0c;实现的是不同的优化算法的&#xff08;不同CCL库最大的区别就是这&#xff09; 不同CCL库还会根据自己的硬件、系统&#xff0c;在底层上面对一些相对应的改动&#xff1b; 但是对上的API接口…

【数据结构篇】时间复杂度

一.数据结构前言 1.1 数据结构的概念 数据结构(Data Structure)是计算机存储、组织数据的⽅式&#xff0c;指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤&#xff0c;所以我们要学各式各样的数据结构&#xff0c; 如&#xff1a…

700. 二叉搜索树中的搜索

二叉搜索树中的搜索 已解答 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&#xff1a;root [4,2,7,1,3], v…

Spring Cloud工程搭建

目录 工程搭建 搭建父子工程 创建父工程 Spring Cloud版本 创建子项目-订单服务 声明项⽬依赖 和 项⽬构建插件 创建子项目-商品服务 声明项⽬依赖 和 项⽬构建插件 工程搭建 因为拆分成了微服务&#xff0c;所以要拆分出多个项目&#xff0c;但是IDEA只能一个窗口有一…

Rust中使用ORM框架diesel报错问题

1 起初环境没有问题&#xff1a;在Rust开发的时候起初使用的是mingw64平台加stable-x86_64-pc-windows-gnu编译链&#xff0c;当使用到diesel时会报错&#xff0c;如下&#xff1a; x86_64-w64-mingw32/bin/ld.exe: cannot find -lmysql具体信息很长这是主要信息是rust找不到链…

【C++】P1765 手机

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;问题描述题目内容示例&#xff1a; 键盘布局 &#x1f4af;我的做法思路问题与优化我的代码实现分析与问题 &#x1f4af;老师的做法思路老师的代码实现分析优点 &#x1f…

本地快速部署DeepSeek-R1模型——2025新年贺岁

一晃年初六了&#xff0c;春节长假余额马上归零了。今天下午在我的电脑上成功部署了DeepSeek-R1模型&#xff0c;抽个时间和大家简单分享一下过程&#xff1a; 概述 DeepSeek模型 是一家由中国知名量化私募巨头幻方量化创立的人工智能公司&#xff0c;致力于开发高效、高性能…

3 卷积神经网络CNN

1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron&#xff0c;可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…

QT交叉编译环境搭建(Cmake和qmake)

介绍一共有两种方法&#xff08;基于qmake和cmake&#xff09;&#xff1a; 1.直接调用虚拟机中的交叉编译工具编译 2.在QT中新建编译套件kits camke和qmake的区别&#xff1a;CMake 和 qmake 都是自动化构建工具&#xff0c;用于简化构建过程&#xff0c;管理编译设置&…

STM32 对射式红外传感器配置

这次用的是STM32F103的开发板&#xff08;这里面的exti.c文件没有how to use this driver 配置说明&#xff09; 对射式红外传感器 由一个红外发光二极管和NPN光电三极管组成&#xff0c;M3固定安装孔&#xff0c;有输出状态指示灯&#xff0c;输出高电平灯灭&#xff0c;输出…

SQL优化

1.插入数据 &#xff08;1&#xff09;insert优化 批量插入&#xff1a;insert into tb_test values(1,tom),(2,cat),(3.jerry); 手动提交事务&#xff1a; start transaction; insert into tb_test values(1,tom),(2,cat),(3.jerry); insert into tb_test values(12,tom),(22…

BFS(广度优先搜索)——搜索算法

BFS&#xff0c;也就是广度&#xff08;宽度&#xff09;优先搜索&#xff0c;二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS&#xff08;深度优先搜索&#xff09;。从字面意思也很好理解&#xff0c;DFS就是一条路走到黑&#xff0c;BFS则是一层一层地展开。…

单调队列 滑动窗口(题目分析+C++完整代码)

滑动窗口/单调队列 原题链接 AcWing 154. 滑动窗口 题目描述 给定一个数组。 有一个大小为 k的滑动窗口&#xff0c;它从数组的最左边移动到最右边。 你只能在窗口中看到 k个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子&#xff1a; 该数组为 [1 3 -1 -3 5 3 6 7…

爬虫基础(四)线程 和 进程 及相关知识点

目录 一、线程和进程 &#xff08;1&#xff09;进程 &#xff08;2&#xff09;线程 &#xff08;3&#xff09;区别 二、串行、并发、并行 &#xff08;1&#xff09;串行 &#xff08;2&#xff09;并行 &#xff08;3&#xff09;并发 三、爬虫中的线程和进程 &am…

【C++】B2120 单词的长度

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;我的做法代码实现&#xff1a;思路解析&#xff1a; &#x1f4af;老师的第一种做法代码实现&#xff1a;思路解析&#xff1a; &#x1f4af;老师的…

nvm的安装和使用

打开地址下载 https://github.com/coreybutler/nvm-windows/releases 推荐下载&#xff0c;nvm-setup.zip 这个。可能有的教程会让下载nvm-noinstall.zip 。noinstall确实下载之后不用安装&#xff0c;但是要自己配置setting.txt文件&#xff0c;以及环境变量 。 安装nvm 在电…

嵌入式知识点总结 操作系统 专题提升(四)-上下文

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.上下文有哪些?怎么理解? 2.为什么会有上下文这种概念? 3.什么情况下进行用户态到内核态的切换? 4.中断上下文代码中有哪些注意事项&#xff1f; 5.请问线程需要保存哪些…

Python在线编辑器

from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…