当前位置: 首页 > news >正文

【综合案例】使用React编写B站评论案例

一、效果展示

默认效果,一开始默认按照最热进行排序
发布了一条评论
按照最新进行排序
按照最新进行排序

二、效果说明

页面上默认有3条评论,且一开始进入页面的时候是按照点赞数量进行倒序排列展示,可以点击【最热 、最新】进行排序的切换。

在文本框中输入要评论的文本,然后点击【发布】按钮,即可将评论添加到下方的评论列表当中进行展示;如果没有输入任何文本的时候直接点击【发布】按钮会弹出提示对话框。

点击删除按钮可以将对应的评论从评论列表中移除。

三、涉及知识点

3.1 useState

3.1.1 基础使用

useState 是一个 React Hook(函数),它允许我们向组件添加一个状态变量, 从而控制影响组件的渲染结果。

🚩 语法:

const [state, setState] = useState(initialState)
  1. useState是一个函数,返回值是一个数组 
  2. 数组中的第一个参数是状态变量;第二个参数是set函数,用来修改状态变量
  3. useState的参数将作为state的初始值

🚩 本质:

和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图)。

注意事项:

  • useState 是一个 Hook,因此你只能在 组件的顶层 或自己的 Hook 中调用它。你不能在循环或条件语句中调用它。如果你需要这样做,请提取一个新组件并将状态移入其中。
  • 在严格模式中,React 将 两次调用初始化函数,以 帮你找到意外的不纯性。这只是开发时的行为,不影响生产。如果你的初始化函数是纯函数(本该是这样),就不应影响该行为。其中一个调用的结果将被忽略。
3.1.2 修改状态的规则

🚩 状态不可变

在React中,状态被认为是只读的,我们应该始终 替换它而不是修改它, 直接修改状态不能引发视图更新。

🚩 修改对象状态

规则:对于对象类型的状态变量,应该始终传给set方法一个 全新的对象 来进行修改。

3.2  classnames优化类名控制

classnames是一个简单的JS库,可以非常方便的 通过条件动态控制class类名的显示。

 

现在的问题:字符串的拼接方式不够直观,也容易出错。
3.3 受控表单绑定

 概念:使用React组件的状态(useState)控制表单的状态。

 1. 准备一个React状态值

const [value, setValue] = useState('')
2. 通过value属性绑定状态,通过onChange属性绑定状态同步的函数
// 通过value属性绑定react状态
// 绑定onChange事件,通过事件参数e拿到输入框最新的值,反向修改到react状态
<inputtype="text"value={value}onChange={(e) => setValue(e.target.value)}/>
3.4  获取DOM

在React组件中获取 / 操作DOM,需要使用useRef React Hook钩子函数,分为两步:

1. 使用useRef创建 ref 对象,并与 JSX 绑定

2. 在DOM可用时,通过 inputRef.current 拿到 DOM 对象

四、代码实现

4.1 逻辑渲染层

import { useRef, useState } from "react";
import './App.scss'
import avatar from './image/bozai.png'
import dayjs from 'dayjs'
import { v4 as uuidV4 } from 'uuid'
import _ from 'lodash'
import classNames from 'classnames'
function App() {// 当前登录用户信息const user = {// 用户iduid: '30009257',// 用户头像avatar,// 用户昵称uname: '嘟嘟嘟',}// 评论列表数据const defaultList = [{// 评论idrpid: 3,// 用户信息user: {uid: '13258165',avatar: require('./image/panda.jpg'),uname: '周杰伦',},// 评论内容content: '哎哟,不错哦',// 评论时间ctime: '10-18 08:15',like: 88,},{rpid: 2,user: {uid: '36080105',avatar: require('./image/panda.jpg'),uname: '许嵩',},content: '我寻你千百度 日出到迟暮',ctime: '11-13 11:29',like: 88,},{rpid: 1,user: {uid: '30009257',avatar,uname: '黑马前端',},content: '学前端就来黑马',ctime: '10-19 09:00',like: 66,},]// 导航 Tab 数组const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },]// 最初的时候先按照最热进行倒叙排列const [remarkList, setRemark] = useState(_.orderBy(defaultList, 'hot', 'desc'))const [content, setContent] = useState('')const inputRef = useRef(null)// 发布评论function handleSubmit() {// 阻止提交空数据if (!content) return alert('请输入评论内容')setRemark([{rpid: uuidV4(),//随机iduser,content,ctime: dayjs(new Date()).format('MM-DD HH:mm'),like: 0,},...remarkList])setContent('')//清空输入框中的内容inputRef.current?.focus()//重新聚焦}// 删除评论function handleDel(item) {setRemark(remarkList.filter(v => v.rpid !== item.rpid))}const [type, setType] = useState('hot')/*** tab切换*  1.点击谁就把谁的type记录下来*  2.通过记录的type和每一项遍历时的type做匹配,控制激活类名的显示*/function handleTabChange(type) {setType(type)if (type === 'time') {// 按照时间倒序setRemark(_.orderBy(remarkList, 'ctime', 'desc'))} else {// 按照点赞数倒序setRemark(_.orderBy(remarkList, 'like', 'desc'))}}return (<div className="App"><div className="top"><div className="left"><span className="l-title">评论</span><span>{remarkList.length}</span></div><div className="right">{/* 高亮类名 */}{/* classnames优化类名控制classnames是一个简单的JS库,可以非常方便的通过条件动态控制class类型的显示*/}{tabs.map((item) => {return (<spanclassName={classNames('nav-item', { active: type === item.type })}key={item.type}onClick={() => handleTabChange(item.type)}>{item.text}</span>)})}</div></div><div className="push"><img className="avatar" src={user.avatar} /><textarea className="textarea" placeholder="发一条友善的评论" ref={inputRef} value={content} onChange={(e) => setContent(e.target.value)}></textarea><button className="pushBtn" onClick={handleSubmit}>发布</button></div><div className="main">{/* 评论项 */}{remarkList.map((item) => {return (<div className="m-item" key={item.rpid}><img className="avatar" src={item.user.avatar} /><div className="mi-right"><div>{item.user.uname}</div><div className="text">{item.content}</div><div ><span>{item.ctime}</span><span className="like">点赞数:{item.like}</span><span onClick={() => handleDel(item)}>删除</span></div></div></div>)})}</div></div>);
}export default App;

4.2 样式层

.App{margin: 10px;
}
.top{margin-bottom: 20px;display: flex;align-items: baseline;font-size: 15px;color: #999;
.left{margin-right: 50px;
.l-title{font-size: 20px;font-weight: 700;color: #000;margin-right: 5px;
}
}
.right{display: flex;flex-direction: row;align-items: center;.nav-item {cursor: pointer;&:hover {color: #00aeec;}&:last-child::after {display: none;}&::after {content: ' ';display: inline-block;height: 10px;width: 1px;margin: -1px 12px;background-color: #9499a0;}}.nav-item.active{color: #000;}
}
}
.push{margin-bottom: 20px;display: flex;
.textarea{margin: 0 10px;padding: 10px;flex: 1;min-height: 30px;max-height: 100px;border-radius: 10px;border: none;outline: none;background-color: #ebebeb;
}
.pushBtn{width: 100px;height: 50px;font-size: 16px;color: #fff;border: none;border-radius: 5px;background-color: rgba(0,174,236,0.5);&:hover{background-color: rgba(0,174,236);}
}
}
.avatar{width: 40px;height: 40px;border-radius: 50%;
}.m-item{display: flex;margin-bottom: 10px;
.mi-right{padding-bottom: 10px;margin-left: 10px;flex: 1;font-size: 14px;color: #999;border-bottom: 1px solid #e4e3e3;
}
.text{margin: 10px 0;color: #000;
}
.like{margin: 0 20px;
}
}

相关文章:

【综合案例】使用React编写B站评论案例

一、效果展示 默认效果&#xff0c;一开始默认按照最热进行排序 发布了一条评论 按照最新进行排序 按照最新进行排序 二、效果说明 页面上默认有3条评论&#xff0c;且一开始进入页面的时候是按照点赞数量进行倒序排列展示&#xff0c;可以点击【最热 、最新】进行排序的切换。…...

【AIGC】腾讯云语音识别(ASR)服务在Spring Boot项目中的集成与实践

腾讯云语音识别&#xff08;ASR&#xff09;服务在Spring Boot项目中的集成与实践 引言 在现代软件开发中&#xff0c;语音识别技术的应用越来越广泛&#xff0c;从智能助手到自动客服系统&#xff0c;语音识别技术都在发挥着重要作用。腾讯云提供了强大的语音识别服务&#…...

基于 Vue3、Vite 和 TypeScript 实现开发环境下解决跨域问题,实现前后端数据传递

引言 本文介绍如何在开发环境下解决 Vite 前端&#xff08;端口 3000&#xff09;和后端&#xff08;端口 80&#xff09;之间的跨域问题&#xff1a; 在开发环境中&#xff0c;前端使用的 Vite 端口与后端端口不一致&#xff0c;会产生跨域错误提示&#xff1a; Access to X…...

前端面筋(持续更新)

额外面筋 get和post的区别&#xff1f;怎么理解get能被缓存&#xff1f; get请求和post同属于http中的两种请求&#xff0c;在传输上没有什么区别&#xff0c;只是约定有所不同get请求一般用于向服务器请求数据 post请求一般用于向服务器提交数据get请求的参数一般不安全&…...

深度学习-迁移学习

深度学习中的迁移学习是通过在大规模数据上训练的模型&#xff0c;将其知识迁移到数据相对较少的相关任务中&#xff0c;能显著提升目标任务的模型性能。 一、迁移学习的核心概念 源任务&#xff08;Source Task&#xff09;与目标任务&#xff08;Target Task&#xff09;&…...

6.0、静态路由

路由器最主要的功能就是转发数据包。路由器转发数据包时需要查找路由表&#xff08;你可以理解为地图&#xff09;&#xff0c;管理员可以直接手动配置路由表&#xff0c;这就是静态路由。 1.什么是路由&#xff1f; 在网络世界中&#xff0c;路由是指数据包在网络中的传输路…...

Redis学习:BitMap/HyperLogLog/GEO案例 、布隆过滤器BloomFilter、缓存预热+缓存雪崩+缓存击穿+缓存穿透

Redis学习 文章目录 Redis学习1、BitMap/HyperLogLog/GEO案例2. 布隆过滤器BloomFilter3. 缓存预热缓存雪崩缓存击穿缓存穿透 1、BitMap/HyperLogLog/GEO案例 真实需求面试题 亿级数据的收集清洗统计展现对集合中数据进行统计&#xff0c;基数统计&#xff0c;二值统计&#xf…...

Lua数据类型

Lua 语言 数据类型 Lua 有以下数据类型&#xff1a; nil&#xff1a;表示一个无效值&#xff0c;相当于 NULL。boolean&#xff1a;true 或 false。number&#xff1a;整数或浮点数。string&#xff1a;字符串。function&#xff1a;函数。userdata&#xff1a;用户数据。th…...

CSS中的背景色和前景色

目录 1 对比度的计算1.1 亮度计算1.2 对比度比率 2 在线计算对比度 在我们的样式设计中&#xff0c;通常会有背景色和前景色的概念。前景色我们通常用来设置文本的颜色&#xff0c;而背景色通常是文本的所在容器的颜色。比如如果我们把文本放在普通容器里&#xff0c;那普通容器…...

伊莱亚斯 M. 斯坦恩(Elias M. Stein)《复分析》与《实分析》教材

分析学大师Elias M. Stein&#xff08;曾是陶哲轩的老师&#xff09;&#xff0c;写了四本分析学系列教材&#xff0c;统称为普林斯顿分析学讲座&#xff08;Princeton Lectures in Analysis&#xff09;。他们分别是&#xff1a; I Fourier Analysis&#xff1a;An Introduct…...

UCLA、MIT数学家推翻39年经典数学猜想!AI证明卡在99.99%,人类最终证伪

39年来一个看似理所当然的数学理论&#xff0c;刚刚被数学家证伪&#xff01;UCLA和MIT的研究者证实&#xff1a;概率论中众所周知的假设「上下铺猜想」是错的。有趣的是&#xff0c;他们用AI已经证明到了99.99%的程度&#xff0c;但最终&#xff0c;靠的还是理论论证。 又一个…...

大厂面试真题-很多系统会使用netty进行长连接,连接太多会有问题吗

使用Netty进行长连接时&#xff0c;机器数量过多确实可能会因为连接数量过多而引发问题。这些问题主要涉及系统资源消耗、连接管理、性能优化等方面。以下是对这些潜在问题的详细分析&#xff1a; 一、系统资源消耗 文件句柄限制&#xff1a; 在Linux等操作系统中&#xff0c;…...

Android RecyclerView ,使用ItemDecoration设置边距的大坑:左右边距不均匀/不同,已解决。

写在前面:最近有一个需求,在长宽固定的一块区域内,使用RecyclerView实现APP显示界面,考虑一下使用了网格布局GridLayoutManager,弄成5列的网格。设置边距的时候,使用ItemDecoration设置上、左边距。但是恶心的事情发生了,明明所有Item都设置了同样的左边距,但是只有第一…...

系统上云-流量分析和链路分析

优质博文&#xff1a;IT-BLOG-CN 一、流量分析 【1】流量组成&#xff1a; 按协议划分&#xff0c;流量链路可分为HTTP、SOTP、QUIC三类。 HTTPSOTPQUIC场景所有HTTP请求&#xff0c;无固定场景国内外APP等海外APP端链路选择DNS/CDN(当前特指Akamai)APP端保底IP列表/动态IP下…...

Apache 配置出错常见问题及解决方法

Apache 配置出错常见问题及解决方法 一、端口被占用问题 问题描述:在启动 Apache 时,出现“Address already in use”或类似的错误提示,这意味着 Apache 想要使用的端口已经被其他程序占用,导致 Apache 无法正常启动。原因分析: 系统中已经有其他的应用程序在使用 Apache…...

DGL库之dgl.function.u_mul_e(代替dgl.function.src_mul_edge)

DGL库之dgl.function.u_mul_e 语法格式例子 语法格式 dgl.function.u_mul_e代替了dgl.function.src_mul_edge dgl.function.u_mul_e(lhs_field, rhs_field, out)一个用于计算消息传递的内置函数&#xff0c;它通过对源节点&#xff08;u&#xff09;和边&#xff08;e&#x…...

题目练习之二叉树那些事儿

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ 知道了二叉树的结…...

数字马力二面面试总结

24.03.07数字马力二面面试总结 前段时间找工作,做的一些面试笔记总结 大家有面试录音或者记录的也可以发给我,我来整理答案呀 数字马力二面面试总结 24.03.07数字马力二面面试总结你可以挑一个你的最有挑战性的,有难度的,最具有复杂性的项目,可以简单说一下。有没有和算…...

优化图片大小的方法

不能起到优化图片大小的方法有&#xff08;C&#xff09; A.减少每个像素点能够显示的颜色 B.减少像素点 C.使用ajax加载 D.使用WebP格式 C. 使用Ajax加载 Ajax是一种用于在网页中异步加载数据的技术&#xff0c;与图片大小的优化关系不大。它主要用于提高网页的加载效率&…...

DevOps-课堂笔记

各种 aaS 类比于计算机网络的 OSI 参考模型&#xff0c;一个软件应用项目需要不同的支撑层&#xff0c;例如从下至上大概需要&#xff1a; 硬件层面的服务器针对硬件做弹性分配的虚拟化机制&#xff0c;例如虚拟机在虚拟化环境内运行的 OS支撑软件应用的中间件&#xff0c;例…...

Redis - Hash 哈希

一、基本认识 ⼏乎所有的主流编程语⾔都提供了哈希&#xff08;hash&#xff09;类型&#xff0c;它们的叫法可能是哈希、字典、关联数 组、映射。在Redis中&#xff0c;哈希类型是指值本⾝⼜是⼀个键值对结构&#xff0c;形如key"key"&#xff0c;value{{ field1, v…...

dns服务部署

配置主文件&#xff0c;编辑主配置文件设置监听IP &#xff0c; 重启服务&#xff1a;[rootlocalhost ~]# systemctl restart network 安装bind 主服务器IP信息&#xff1a; [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 129.168.160.131/24…...

【Hadoop和Hbase集群配置】3台虚拟机、jdk+hadoop+hbase下载和安装、环境配置和集群测试

目录 一、环境 二、虚拟机配置 三、 JDK、Hadoop、HBase的安装和配置 【安装和配置JDK】 【安装和配置Hadoop】 【安装和配置Hbase】 四、 Hadoop和HBase集群测试 【Hadoop启动测试】 【Hbase启动测试】 一、环境 OS: CentOS-7 JDK: v1.8.0_131 Hadoop: v2.7.6 Hb…...

超萌!HTMLCSS:超萌卡通熊猫头

效果演示 创建了一个卡通风格的熊猫头 HTML <div class"box"><div class"head"><div class"head-copy"></div><div class"ears-left"></div><div class"ears-right"></di…...

人脑与机器连接:神经科技的伦理边界探讨

内容概要 在当今科技飞速发展的时代&#xff0c;人脑与机器连接已成为一个引人注目的前沿领域。在这一背景下&#xff0c;神经科技的探索为我们打开了一个全新的世界&#xff0c;从脑机接口到人工智能的飞跃应用&#xff0c;不仅加速了技术的进步&#xff0c;更触动了我们内心…...

Mac M1 Docker创建Rocketmq集群并接入Springboot项目

文章目录 前言Docker创建rocketmq集群创建rocketmq目录创建docker-compose.yml新增broker.conf文件启动容器 Springboot 接入 rocketmq配置maven依赖修改appplication.yml新增消息生产者新增消费者测试发送消息 总结 前言 最近公司给配置了一台mac&#xff0c;正好有时间给装一…...

k8s 查看cpu使用率最高的pod

在 Kubernetes 中&#xff0c;可以使用 kubectl top 命令查看 Pod 的资源使用情况&#xff0c;从而找到 CPU 使用率最高的 Pod。 步骤 使用 kubectl top pods 查看所有 Pod 的 CPU 使用情况 运行以下命令查看集群中所有 Pod 的 CPU 和内存使用情况&#xff1a; kubectl top po…...

jenkins 构建报错 Cannot run program “sh”

原因 在 windows 操作系统 jenkins 自动化部署的时候, 由于自动化构建的命令是 shell 执行的,而默认windows 从 path 路径拿到的 shell 没有 sh.exe &#xff0c;因此报错。 解决方法 前提是已经安装过 git WINR 输入cmd 打开命令行, 然后输入where git 获取 git 的路径, …...

Netty ByteBuf 分配 | 池化复用 、直接内存

Netty ByteBuf 分配 本文主要内容关于 ByteBuf 分配介绍&#xff0c;为了更好的理解本文&#xff0c;我们可以带着几个问题思考 在IO密集型业务场景下&#xff0c;可能涉及大量ByteBuf分配&#xff0c;这时我们需 要考虑会不会产生OOM会不会出现频繁GC会不会内存泄露 根据上…...

【数据结构】堆和二叉树(2)

文章目录 前言一、建堆和堆排序1.堆排序 二、二叉树链式结构的实现1.二叉树的遍历 三、链式二叉树的功能函数1.二叉树结点个数2.二叉树叶子结点个数3.二叉树的高度4.二叉树第k层结点个数5. 二叉树查找值为x的结点6.二叉树销毁 总结 前言 接着上一篇博客&#xff0c;我们继续分…...