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

【react案例】实现评论列表

1. 需求

在这里插入图片描述

  1. 展示评论列表
  2. 实现删除功能
    2.1 只有自己的评论才展示删除按钮
    2.2 点击删除按钮,删除当前评论
  3. tab切换(点击对应tab,对tab文案高亮处理)
  4. 评论高亮
  5. 评论排序(最新、最热)

2. 实现思路

  1. useState维护评论列表
  2. map方法遍历渲染
  3. 删除显示——条件渲染
  4. 删除功能——拿到当前评论项的id,然后对原有评论列表进行过滤,根据id剔除要删除的评论项
  5. tab高亮——记录点击的tab的type,根据type去匹配高亮样式
  6. 评论排序——根据tab的type对评论列表状态数据进行不同的排序处理,当成新值传给set方法重新渲染视图UI(注意:排序后不要修改评论列表状态数据的原始值,教程里推荐使用lodash包的orderBy方法)

3. 代码

  • 样式是我自己随便写的,具体可以参考b站本身的css样式
3.1 App.js
import { useState } from "react"
import _ from 'lodash'
import './App.css'function App() {// 评论列表const initReviewList = [{rid: 2,user: {uid: '002',avator: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.gC14cncyeUsZYKNwXOyBtgHaHa?rs=1&pid=ImgDetMain',uname: '小猫爱吃鱼'},content: '喵喵喵',ctime: '09-22 17:55',like: 90},{rid: 1,user: {uid: '001',avator: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.qCys2C8LjF8c3_UHbGOooAAAAA?rs=1&pid=ImgDetMain',uname: '小狗爱吃骨头'},content: '汪汪汪',ctime: '09-22 14:55',like: 100},{rid: 0,user: {uid: '000',avator: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.pL9aeO50HMujMSzGcOPhKwAAAA?rs=1&pid=ImgDetMain',uname: '二郎神'},content: '666',ctime: '09-30 12:23',like: 88}]// 当前登录的用户信息const user = {uid: '000',avator: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.pL9aeO50HMujMSzGcOPhKwAAAA?rs=1&pid=ImgDetMain',uname: '二郎神'}// tabconst tabs = [{type: 'hot',text:'最热',},{type: 'new',text:'最新',}]const [reviewList, setReviewList] = useState(_.orderBy(initReviewList, 'like', 'desc'))function handleDeleteReview(currentRid) {setReviewList(reviewList.filter(item=> item.rid !== currentRid))}const [currTabType, steCurrTabType] = useState('hot')function handleClickTab(type) {steCurrTabType(type)if (type === 'hot') {// 根据点赞数量,降序排序setReviewList(_.orderBy(reviewList, 'like', 'desc'))} else {// 根据评论时间,降序排序setReviewList(_.orderBy(reviewList, 'ctime', 'desc'))}}return (<div className="App">{/* 导航栏 */}<div className="review-header">{/* 标题 */}<div className="review-title-container"><span className="review-title">评论</span>{/* 评论总数 */}<div className="review-total">{reviewList.length ?? 0}</div></div><div className="review-tabs-container">{tabs.map((item, index) => {return <div key={item.type} className="tabs-item"><span className={`tabs-text ${item.type === currTabType && 'tabs-active'}`} onClick={() => handleClickTab(item.type)}>{item.text}</span>{index < tabs.length - 1 && <div className="tabs-idot">|</div>}</div>})}</div></div>{/* 评论 */}<div className="review-wrap">{/* 发表评论 */}<div className="box-normal"><img className="normal-avator" src={user.avator}></img><input className="review-input" placeholder="发一条友善的评论"></input><button className="add-review">发布</button></div>{/* 评论列表 */}<div className="review-list">{reviewList.map((item) => {{/* 每一条评论 */ }return <div className="review-item" key={item.rid}>{/* 头像 */}<img className="review-avator" src={item.user.avator}></img><div className="review-item-content">{/* 用户名 */}<div className="user-name">{item.user.uname}</div>{/* 评论内容 */}<span className="review-content">{item.content}</span>{/* 评论相关信息 */}<div className="review-msg">{/* 评论时间 */}<span className="review-date">{item.ctime}</span>{/* 点赞数量 */}<span className="good-count">点赞数:{item.like}</span>{/* 删除评论按钮 */}{item.user.uid === user.uid && <span className="review-delete" onClick={() => handleDeleteReview(item.rid)}>删除</span>}</div>{/* 分割线 */}<div className="part-line"></div></div></div>})}</div></div></div>);
}export default App;
3.2 App.css
.review-header {display: flex;.review-title-container {display: flex;align-items: center;margin-right: 40px;.review-title {font-weight: bold;margin-right: 2px;}.review-total {font-size: 12px;color: gray;}}.review-tabs-container {display: flex;align-items: center;font-size: 12px;font-weight: bold;.tabs-item {color: gray;display: flex;.tabs-text {cursor: pointer;}.tabs-active {color: black;}.tabs-idot {margin: 0px 5px;}}}
}.box-normal {display: flex;margin: 16px 0px 30px 0px;.normal-avator {width: 50px;height: 50px;border-radius: 50%;margin-right: 20px;}.review-input {border: 1px solid #F1F2F3;background-color: #F1F2F3;border-radius: 6px;padding-left: 10px;}.add-review {background-color: skyblue;border: transparent;border-radius: 6px;color: #fff;margin-left: 6px;padding: 0px 10px;}
}.review-list {.review-item {display: flex;margin-bottom: 15px;.review-avator {width: 50px;height: 50px;border-radius: 50%;margin-right: 20px;}.review-item-content {.user-name {font-size: 12px;font-weight: bold;color: gray;margin-bottom: 6px;}.review-content {font-size: 14px;}.review-msg {font-size: 10px;color: gray;.review-date {margin-right: 15px;}.good-count {margin-right: 15px;}.review-delete {cursor: pointer;}}.part-line {margin-top: 5px;height: 0.5px;background-color: #E3E5E7;}}}
}
3.3 效果图

在这里插入图片描述

参考

黑马程序员react教程

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 108.游戏安全项目:信息显示二-剑侠情缘基址分析
  • 委托和事件
  • Qt 之自定义控件(开关按钮)
  • Django Web开发基础介绍
  • Milvus - 架构设计详解
  • java 解析excel (本地资源)
  • LeetCode 2535.数组元素和与数字和的绝对差:模拟
  • Halcon基础系列1-基础算子
  • 【C++算法】2.双指针_复写零
  • 深入理解 CompletableFuture 的底层原理
  • 计算机视觉硬件整理(四):相机与镜头参数介绍
  • 【Kubernetes】常见面试题汇总(三十四)
  • python的逻辑控制
  • 高刷显示器哪个好?540Hz才有资格称高刷
  • 重修设计模式-行为型-责任链模式
  • 自己简单写的 事件订阅机制
  • [译] 怎样写一个基础的编译器
  • gf框架之分页模块(五) - 自定义分页
  • Git 使用集
  • HTTP请求重发
  • leetcode98. Validate Binary Search Tree
  • Linux快速复制或删除大量小文件
  • spring学习第二天
  • SQLServer之索引简介
  • Vue实战(四)登录/注册页的实现
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 技术:超级实用的电脑小技巧
  • 如何解决微信端直接跳WAP端
  • 实习面试笔记
  • 说说动画卡顿的解决方案
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • HanLP分词命名实体提取详解
  • mysql面试题分组并合并列
  • # C++之functional库用法整理
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #mysql 8.0 踩坑日记
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (3)(3.5) 遥测无线电区域条例
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (c语言+数据结构链表)项目:贪吃蛇
  • (Matlab)使用竞争神经网络实现数据聚类
  • (二)linux使用docker容器运行mysql
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (黑马C++)L06 重载与继承
  • (理论篇)httpmoudle和httphandler一览
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转载)深入super,看Python如何解决钻石继承难题
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案
  • .netcore 获取appsettings