react中JSX基础与useState的基本使用 + 评论显示删除需求案例
参考视频:https://www.bilibili.com/video/BV1ZB4y1Z7o8/?p=3&spm_id_from=pageDriver&vd_source=5c584bd3b474d579d0bbbffdf0437c70
如果没有安装create-react-app需要先全局安装
命令:npm i -g create-react-app
1.快速搭建开发环境
create-react-app是一个快速 创建react开发环境的工具,底层由webpack构建,封装了配置细节,开箱即用
执行命令:
npx create-react-app react-basic
- npx Node.js工具命令,查找并执行后续的包命令
- create-react-app 核心包(固定写法),用于创建react项目
- react-basic React项目的名称(可以自定义)
- 创建React项目的更多方式:https://zh-hans.react.dev/learn/start-a-new-react-project
2.项目文件
src/index.js ==> 入口文件
src/App.js ==>导入项目的根组件
3.JSX基础:概念和本质
- 概念:
JSX是Javascript和XML(HTML)的缩写,表示在JS代码中编写HTML模板结构,它是React中编写UI模板的方式
优势:
- HTML的声明式模板写法
- JS的可编程能力
- 本质:
JSX并不是标准的JS语法,它是JS的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能在浏览器中运行。 (babel解析工具)
babel网址:babeljs.io , 可以在左边输入js代码看右边编译在浏览器运行的代码,需要把react勾上才能解析JSX
- 高频场景:
- JSX中使用JS表达式:在JSX中可以使用大括号语法{}识别Javascript中的表达式,比如常见的变量、函数调用、方法调用等等。
1.使用引号传递字符串 2.使用Javascript变量 3.函数调用和方法调用 4.使用Javascript对象
function getName() {return 'jack'
}
function Contuer() {const count = 100;return(<div>{/* 1.使用引号传递字符串, 字符串识别 */}{ 'this is message' }{/* 2.使用Javascript变量, 识别js变量 */}{ count }{/* 3.函数调用和方法调用 */}{ getName() } {/* 调用函数显示的是函数的返回值 */}{ new Date().getDate() } {/* 方法调用 */}{/* 4.使用Javascript对象, {}外层是识别对象的 */}<div style={{color: 'red'}}>this is div</div></div>)
}
注意:if语句、switch语句、变量声明属于语句,不是表达式,不能出现在{}中
4.JSX基础-实现列表渲染
map循环哪个结构直接return结构,通过map渲染需要绑定独一无二的key 字符串或者number,key的作用:React框架内部使用 提升更新性能的
5.JSX基础-实现条件渲染
语法:在React中,可以通过逻辑与运算符&&、三元表达式(?:)实现基础的条件渲染
{flag && <span>this is span</span>} // 判断一种情况,如果flag为true,span就显示,否则span不显示
{loading ? <span>loading...</span> : <span>加载完成</span>} // 两种情况(多个),loading为true就显示loading...,否则显示加载完成
6.JSX基础-复杂条件渲染
需求:列表中需要根据文章状态适配三种情况,单图、三图和无图三种模式
解决方案:自定义函数 + if 判断语句
const articleType = 3 // 0 1 3三种模式
function getArticleTem() {// 可以用switch做if (articleType === 0) {return <div>无图</div>} else if (articleType === 1) {return <div>一图</div>} else {return <div>三图</div>}
}
function Couter() {return(<div>{ getArticleTem() } {/* 调用函数渲染不同的模板 */}</div>)
}
8.React中的时间绑定
语法: on + 事件名称 = { 事件处理程序 }, 整体上遵循驼峰命名法
- 使用事件对象参数
- 传递自定义参数
- 同时传递事件对象和自定义参数
9.React组件基础使用
组件是什么?
概念:一个组件就是用户界面的一部分,它可以有自己的逻辑和外观,组件之间可以互相嵌套,也可以复用多次
组件化开发可以让开发者像搭积木一样构建一个完整的庞大的应用
在React中,一个组件就是首字母大写的函数(规定好的),内部存放了组建的逻辑和视图UI,渲染组件只需要把组件当成标签书写即可
function Button(){return <button>click me</button>
}
不一定非要function Button(){}, const Button = () => {}也是可以的,只要是首字母大写的函数就是组件
const Button = () => {return <button>click me</button>
}
10.useState基础使用
useState是一个React Hook(函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果
本质:和普通JS变量不同的是,状态变量一旦发生变化组建的视图UI也会跟着变化(数据驱动视图)
- useState修改状态的规则
- 修改对象状态
11.React组件基础样式控制
- 组件基础样式方案
使用style={{fontSize: '20px'}时,如果样式有带-的要改为驼峰写法}。使用class时<span className="class-name">span...</span>class要改为className
12.评论案例
12.1 列表渲染
思路:
- 使用useState维护评论列表
- 使用map方法对列表数据进行遍历渲染(别忘了加key)
-------------------------------------思考:为什么要用useState来维护评论列表?-----------------------------------
因为函数组件没有生命周期,执行完毕就结束了,即使值改变了,视图也不会更新。而用useState保存的数据改变之后会更新视图如图所示:
当点击事件发生,console.log(‘执行了’)也只会打印刚加载的一次,数据已经加上去了,但是视图还是两项没有更新
--------------------------------------------------思考结束:分割线--------------------------------------------
// 项目的根组件,组件从这往下分散
// App -> 引入到index.js -> 被里面的代码渲染到 public/index.html(root)import { useState } from 'react';
const list = [{name: 'jack',content: '这是评论回复111',time: '2023-6-10',likeNum: 100,uid: '1'},{name: 'rose',content: '这是评论回复222',time: '2023-6-11',likeNum: 230,uid: '2'}
]
const user = {uid: '3002017',avatar: '',uname: '张三'
}// 渲染评论列表
// 1.使用useState维护list
function App() {const [commentList, setCommentList] = useState(list);return (<div className="App"><span>评论{commentList.length}</span> <button>最新</button>|<button>最热</button><div>{user.uname}<input /><button>发布</button></div><div>{commentList.map(item => {return (<div key={item.uid}><div>{item.name}</div><div>{item.content}</div><div><span>{item.time}</span><span>点赞数:{item.likeNum}</span><button>删除</button></div></div>)})}</div></div>);
}export default App;
- 实现评论删除
做两件事情:删除按钮判断当前项里的uid是否等于用户uid,如果相等则显示删除按钮,如果不等不显示删除按钮
给删除按钮绑定点击事件,当点击删除按钮时传入当前项的uid,在事件中用数组过滤掉当前项
const handleDelete = (uid) => {setCommentList(commentList.fliter(item => item.uid !== uid));
}
12.2 渲染tab + 点击高亮实现
map渲染tab数组之后,绑定一个点击事件,传当前项的type,判断当前项的type是否等于一个记录的值,如果相等就让字体颜色高亮
const [tabType, setTabType] = useState(0);
const handleTab = (type) => {setTabType(type);
}return内:
{tab.map(item => <span key={item.type} style={{color: tabType === item.type? 'blue' : '#aaa'}} onClick="() => handleTab(type)">{item.value}</span>)}
12.3 排序功能实现
- 排序可以使用lodash,会生成一份全新的数据,不会更改老数据
lodash官网:lodash.com / lodash.com/docs/
如果需要进来就按第一个高亮的排序,就在初始加载数据那排序
- 用array.sort()给数组排序
// 项目的根组件,组件从这往下分散
// App -> 引入到index.js -> 被里面的代码渲染到 public/index.html(root)import { useState } from 'react';
const list = [{name: 'jack',content: '这是评论回复111',time: '2023-6-10',likeNum: 100,uid: '1'},{name: 'rose',content: '这是评论回复222',time: '2023-6-11',likeNum: 230,uid: '2'},{name: '张三',content: '这是评论回复333',time: '2023-6-9',likeNum: 320,uid: '3'},
]
const tab = [{type: 'time',value: '最新'},{type: 'likeNum',value: '最热'}
]
const user = {uid: '3',avatar: '',uname: '张三'
}// 渲染评论列表
// 1.使用useState维护list
function App() {const [commentList, setCommentList] = useState(list);const [tabType, setTabType] = useState();const handleDelete = (uid) => {// 拿到需要删除uid的评论setCommentList(commentList.filter(item => item.uid !== uid ));}const hanldeTab = (type) => {// 拿到点击的type值setTabType(type);// 基于列表的排序if (type === 'time') {// 根据时间排序setCommentList(commentList.sort((a,b) => {return new Date(b.time).getTime() - new Date(a.time).getTime();}))} else {// 根据点赞数排序setCommentList(commentList.sort((a,b) => {return b.likeNum - a.likeNum;}))}}return (<div className="App"><span>评论{commentList.length}</span>{tab.map(item => <span key={item.type} style={{padding: '9px',color: tabType === item.type ? 'blue' : '#aaa', cursor: 'pointer'}}onClick={() => hanldeTab(item.type)}>{item.value}</span>)}<div>{user.uname}<input /><button>发布</button></div><div>{commentList.map(item => {return (<div key={item.uid}><div>{item.name}</div><div>{item.content}</div><div><span>{item.time}</span><span>点赞数:{item.likeNum}</span>{ item.uid === user.uid && <button onClick={() => handleDelete(item.uid)}>删除</button> }</div></div>)})}</div></div>);
}export default App;
12.4发表评论
1.获取评论内容
const [content, setContent] = useState();<input type="text" value={content} onChange={(e) => setContent(e.target.value)}>2.点击发布按钮发布评论
const handlePublish = () => {setCommentList([...commentList,{name: user.uname,content: content,time: new Date(),likeNum: 0,uid: user.uid}])
}
<button onClick={handlePublish}></button>
- 随机id可以使用uuid: git上搜索:uuidjs/uuid
- 日期时间格式化可以使用dayjs:dayjs官网:dayjs.gitee.io/zh-CN/
12.5清空内容并重新聚焦
import { useRef, useState } from 'react';
const [content, setContent] = useState(''); // 绑定input的value需要加初始值,否则会报错
const inputRef = useRef(null);
const handlePublish = () => {// ...做发布的逻辑// 1.清空输入框的内容setContent('');// 2.重新聚焦 dom(useRef) - focus()inputRef.current.focus();
}<input type="text" ref={inputRef} value={content} onChange={(e) => setContent(e.target.value)} />
<button onClick={handlePublish}>发布</button>
13.classnames工具优化类名控制
用classNames库之后使用方法:
1.命令安装classnames包
npm install classnames2.在组件中引入
import classNames from 'classname';3.在组件内使用, ‘’包裹的是静态的class,
{// active是动态的class名,值是判断条件,是否需要加active这个classactive: type === item.type
}包裹的是动态的class从这样的:nav-item为静态class类名,active为动态class类名
<span className={`nav-item ${type === item.type && 'active'}`}>span...</span>变成这样:
<span className = {classNames('nav-item', {active: type === item.type
})}>span...</span>
相关文章:

react中JSX基础与useState的基本使用 + 评论显示删除需求案例
参考视频:https://www.bilibili.com/video/BV1ZB4y1Z7o8/?p3&spm_id_frompageDriver&vd_source5c584bd3b474d579d0bbbffdf0437c70 如果没有安装create-react-app需要先全局安装 命令:npm i -g create-react-app1.快速搭建开发环境 create-re…...

【OpenCV实现鼠标绘图,轨迹栏做调色板,图像的基本操作】
文章目录 鼠标绘图轨迹栏做调色板图像的基本操作 鼠标绘图 在OpenCV中操作鼠标事件 函数:cv.setMouseCallback() 目的是在鼠标双击的地方画一个圆。首先,我们需要创建一个鼠标回调函数,该函数会在鼠标事件发生时执行。鼠标事件包括左键按下…...

2023年中国自动排气阀产业链、市场规模及存在问题分析]图[
自动排气阀是一种用于排除管道、容器或设备中累积的空气或气体的装置。在液体流动系统中,气体或空气可能会积聚在管道或容器中,影响流体流动、导致气锁和能效降低。自动排气阀的作用是在系统中的气体达到一定压力时,自动地释放气体࿰…...

服务器往浏览器推消息(SSE)应用
1,SSE 和 WebSocket 对比 SSE(服务器发送事件) SSE是一种基于HTTP的单向通信机制,用于服务器向客户端推送数据。它的工作原理如下: 建立连接:客户端通过发送HTTP请求与服务器建立连接。在请求中ÿ…...
Choreographer
系统面试的时候常会遇到,比如它是什么,是用来做什么用的。或许我们大概清楚,但不一定能表达清楚。 在Android框架中,Choreographer(舞台监督)是一个用于管理和协调UI线程上的动画和绘制操作的系统组…...

CentOS有IP地址,连接不上Xshell或使用Xshell时突然断开
问题原因:未在电脑主机的网络中进行IP地址配置 解决办法: 1.打开控制面板,选择‘网络与共享中心’ 2.选择“更改适配器设置” 3.右键点击以太网3“属性” 4.选择协议版本4,点击属性 5.IP地址填写CentOS的IP地址:192.…...

工业电子中的深力科分享一款PWM控制器 KA3525A
关于PWM控制器: PWM控制器是一种用于控制电机或其他设备的电路,它通过改变脉冲宽度调制(PWM)信号的占空比来控制设备的输出。PWM控制器可以使用单片机或开发板等设备来实现,通过设定占空比,可以轻松地控制…...

【小白专用】安装Apache2.4+ 安装PHP8.2+ php与sql server 2008 r2连接测试教程
PHP安装 1、PHP下载 PHP For Windows: Binaries and sources Releases 注意: 1.要下载Thread Safe,否则没有php8apache2_4.dll这个文件 2.如果是64位系统要下载x64的,x86的不行 3.下载Zip 2、PHP解压安装 将Zip进行解压,里…...
408计算机网络知识点简记 (背诵用
1. 物理层 1. 奈氏和香农 意义不同:奈氏准则鼓励用更优编码码元(2W是码元/s);香农给出数据传输上限C(1. 不可能高过C,2. 若低于C,一定有手段做到C) C = W ∗ l o g 2 ( 1 + S N ) C =W * log_2(1+\frac{S}{N}) C=W∗log2(1+NS) 信噪比 = 10 ∗ l o g 10 ( S N …...
SQL*PLUS对文本长度的限制
SQL*PLUS对文本长度的限制 一、可解决SQL * Plus行长限制的部分选项:二、SQL * plus 因为以上限制导致脚本执行过程可能遇到的错误1、CLOB字段超4000报ORA-22835或ORA-017042、CLOB处理:SP2-0027: 输入太长 (> 2499 个字符) 收到错误SP2-0027…...
配置Insecure Docker Registry支持http请求 (更改默认的https请求)
文章目录 小结问题解决参考 小结 本文记录了如何配置Insecure http docker registry,也就是使用http请求 (更改默认的https请求)Docker Registry仓库。 问题 在测试环境中没有配置SSL/TLS, 需要使用http请求Docker Registry&am…...

BAT032:批量替换当前目录下文件的部分字符
引严:编写批处理程序,实现批量替换当前目录下文件的部分字符。 一、新建Windows批处理文件 参考博客: CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.右键新建的批处理文件,点击【编辑】。…...

uni-app:js实现数组中的相关处理
一、查询数组中,某一项中的某个数据为指定值的项(find() 方法) 使用分析 使用数组的 find() 方法来查询 id 为 0 的那一项数据。这个方法会返回满足条件的第一个元素,如果找不到符合条件的元素,则返回 undefined。使用…...

51系列—基于51单片机的数字频率计(代码+文档资料)
本文主要说明基于51单片机的数字频率计设计,完整资料见文末链接 数字频率计概述 数字频率计是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。它是一种用十进制数字显示被测信号频率的数字测量仪器。它的基本功能是测量正弦信号,方波信…...
【SA8295P 源码分析 (四)】44 - 如何替换 NON-HLOS.bin 中的 Wifi Firmware 固件
【SA8295P 源码分析】44 - 如何替换 NON-HLOS.bin 中的 Wifi Firmware 固件 1、提取 NON-HLOS.bin 中的 Wifi Firmware 出来2、把提取出来的 wifi 固件放到代码中3、重新打包生成 NON-HLOS.bin4、将生成的 NON-HLOS.bin 与 老的 NON-HLOS.bin 对比5、使用fastboot 下载测试wifi…...
Aspect Android埋点统计activity页面使用时长 onResume onPause,并保存时长
Aspect Android埋点统计activity页面使用时长 onResume onPause,并保存时长 标记: 1.项目下build.gradle dependencies {classpath com.android.tools.build:gradle:3.5.4classpath com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10 } 2.…...
第四章 选择结构程序设计
C语言有两种选择语句:(1)if语句,实现两个分支的选择结构; (2)Switch语句,实现多分支的选择结构。 1.求ax^2bxc0方程的解。 #include<stdio.h> #include<math.h> int …...
JAVA高级教程-Java List(2)
目录 3、List接口的使用(1)3、List接口的使用(3)4、排序,集合之间的转换 3、List接口的使用(1) package ArrayList01;import java.util.ArrayList; import java.util.Iterator; import java.ut…...

Spark--经典SQL50题
目录 连接数据库准备工作 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数 3、查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩 4、查询平均成绩…...

数据结构: AVL树
目录 1.AVL树的概念 2.AVL树的模拟实现 AVL树的结构定义 插入 对平衡因子的讨论 旋转 对旋转情况的讨论 1.单旋 1.1左单旋 1.2右单旋 2.双旋 2.1左右双旋 2.2右左双旋 检查是否是AVL树 1.AVL树的概念 当向二叉搜索树中插入新结点后,如果能保证每个结点…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...

JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...