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

【React】详解“最新”和“最热”切换与排序

文章目录

    • 一、基本概念和初始化
    • 二、切换与排序功能的实现
      • 1. 函数定义和参数
      • 2. 设置活动 Tab
      • 3. 定义新列表变量
      • 4. 根据排序类型处理列表
        • 4.1 按时间降序排序
        • 4.2 按点赞数降序排序
      • 5. 更新评论列表
    • 三、渲染导航 Tab 和评论列表
      • 1. `map` 方法
      • 2. `key` 属性
      • 3. `className` 动态赋值
      • 4. `onClick` 事件处理器
      • 5. `item.text`
      • 6. `<li>` 容器
    • 四、进阶应用和实际案例
      • 1. 高亮 Tab 和排序状态管理
      • 2. 多条件排序

在现代网页应用中,评论列表是常见的功能模块。为了提高用户体验,我们经常需要对评论进行排序和筛选,以便用户能够更方便地找到感兴趣的内容。本文将深入探讨如何在 React 应用中实现“最新”和“最热”切换与排序功能,涵盖其基本用法、进阶应用以及实际案例。通过本文,你将全面了解如何在 React 应用中有效地实现评论排序功能,并灵活应用于实际项目中。

一、基本概念和初始化

评论数据和用户信息

首先,我们需要一些初始化的数据来展示评论列表。在下面的代码中,我们定义了一个包含评论数据的列表 defaultList 和一个模拟的当前用户 user

// 评论列表数据
const defaultList = [// 每个评论包含 id、用户信息、内容、时间和点赞数{rpid: 3,user: {uid: '13258165',avatar: '',uname: '周杰伦',},content: '哎哟,不错哦',ctime: '10-18 08:15',like: 88,},//....
];// 当前登录用户信息
const user = {uid: '30009257',avatar: 'path/to/avatar.png',uname: '黑马前端',
};

在这些数据中,defaultList 包含了评论的基本信息,包括评论 ID、用户信息、评论内容、时间和点赞数。

二、切换与排序功能的实现

在应用中,提供了两个导航选项卡(Tab):最热最新。用户可以通过点击这两个选项卡来切换评论的排序方式。

// 导航 Tab 数组
const tabs = [{ type: 'hot', text: '最热' },{ type: 'time', text: '最新' },
];

使用 useState 来管理当前选中的 Tab,并通过点击事件更新状态。onToggle 函数用于处理 Tab 的切换逻辑,并对评论列表进行相应的排序。

const [activeTab, setActiveTab] = useState('hot');
const [list, setList] = useState(defaultList);const onToggle = type => {setActiveTab(type);let newList;if (type === 'time') {// 按时间降序排序newList = orderBy(list, 'ctime', 'desc');} else {// 按点赞数降序排序newList = orderBy(list, 'like', 'desc');}setList(newList);
};

在这个函数中,orderBy 函数(来自 lodash 库)根据传入的排序字段(如 ctimelike)和排序顺序(降序)对评论列表进行排序,并更新状态。

1. 函数定义和参数

onToggle 是一个函数,接收一个参数 type,用于指定当前选中的排序类型。这个 type 参数可以是 'time''hot',分别代表“最新”和“最热”两种排序方式。

2. 设置活动 Tab

setActiveTab(type);
  • 功能:调用 setActiveTab 函数来更新当前活动的 Tab。
  • 作用:更新组件的状态,使得用户界面能够反映当前选中的排序方式。例如,如果用户点击了“最新”Tab,setActiveTab 会将 activeTab 的值更新为 'time',从而使得“最新”Tab 高亮显示。

3. 定义新列表变量

let newList;
  • 功能:声明一个变量 newList,用于存储排序后的评论列表。
  • 作用:这个变量将在根据 type 排序评论列表后被赋值。

4. 根据排序类型处理列表

4.1 按时间降序排序
if (type === 'time') {// 按时间降序排序newList = orderBy(list, 'ctime', 'desc');
}
  • 功能:检查 type 是否为 'time'
  • 作用:如果是 'time',则使用 orderBy 函数对 list(评论列表)按 ctime(评论时间)进行降序排序。orderBylodash 库中的一个函数,允许指定排序字段和排序顺序。
  • 具体操作:
    • list 是待排序的数组。
    • 'ctime' 是排序字段,即按照评论时间排序。
    • 'desc' 指定排序顺序为降序。
4.2 按点赞数降序排序
else {// 按点赞数降序排序newList = orderBy(list, 'like', 'desc');
}
  • 功能:如果 type 不是 'time',则认为排序方式是按点赞数排序。
  • 作用:使用 orderBy 函数对 listlike(点赞数)进行降序排序。
  • 具体操作:
    • list 是待排序的数组。
    • 'like' 是排序字段,即按照点赞数排序。
    • 'desc' 指定排序顺序为降序。

5. 更新评论列表

setList(newList);
  • 功能:调用 setList 函数来更新组件状态中的评论列表。
  • 作用:将排序后的 newList 更新到组件状态中,从而使得评论列表的显示顺序根据用户的选择进行更新。

三、渲染导航 Tab 和评论列表

在组件的返回 JSX 中,渲染了 Tab 切换按钮和评论列表。点击 Tab 按钮会触发 onToggle 函数,更新排序方式。

return (<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span><span className="total-reply">{list.length}</span></li><li className="nav-sort">{tabs.map(item => (<divkey={item.type}className={item.type === activeTab ? 'nav-item active' : 'nav-item'}onClick={() => onToggle(item.type)}>{item.text}</div>))}</li></ul></div>{/* 评论列表 */}<div className="reply-list">{list.map(item => (<div key={item.rpid} className="reply-item"><div className="root-reply-avatar"><img className="bili-avatar-img" src={item.user.avatar} alt="" /></div><div className="content-wrap"><div className="user-info"><div className="user-name">{item.user.uname}</div></div><div className="root-reply"><span className="reply-content">{item.content}</span><div className="reply-info"><span className="reply-time">{item.ctime}</span><span className="reply-time">点赞数:{item.like}</span>{user.uid === item.user.uid && (<span className="delete-btn" onClick={() => onDelete(item.rpid)}>删除</span>)}</div></div></div></div>))}</div></div>
);

在这个 JSX 代码中,我们使用条件渲染来应用选中的 Tab 的高亮样式,并通过 onClick 事件绑定到 onToggle 函数,以实现 Tab 切换功能。评论列表的渲染则根据当前的排序方式显示评论项。

1. map 方法

tabs.map(item => (...)) 使用了 Array.prototype.map 方法遍历 tabs 数组,并为每个 item 返回一个 <div> 元素。map 方法会根据数组中的每个元素生成一个新的数组,新的数组中的每个元素是一个 <div> 元素。

2. key 属性

key={item.type}
  • 功能key 属性用于标识数组中每个元素的唯一性,以便 React 能够高效地更新和渲染列表。
  • 作用:这里使用 item.type 作为每个 <div> 元素的 key,因为 type 是唯一的('hot''time')。

3. className 动态赋值

className={item.type === activeTab ? 'nav-item active' : 'nav-item'}
  • 功能:根据当前活动的 Tab (activeTab) 动态设置 <div> 元素的 className
  • 作用:如果当前 item.type 等于 activeTab,则为该 <div> 元素添加 nav-item active 类,使其显示为活动状态(高亮)。否则,仅添加 nav-item 类。

4. onClick 事件处理器

onClick={() => onToggle(item.type)}
  • 功能:为 <div> 元素添加 onClick 事件处理器。
  • 作用:当用户点击某个 Tab 时,调用 onToggle 函数,并将当前 item.type 作为参数传递给 onToggle 函数,从而触发排序逻辑的切换。

5. item.text

{item.text}
  • 功能:在每个 <div> 元素内显示 item.text 的内容。
  • 作用:显示 Tab 文本,分别为“最热”和“最新”。

6. <li> 容器

<li className="nav-sort">...
</li>
  • 功能:将所有生成的 <div> 元素包含在一个 <li> 元素内,并为其添加 nav-sort 类。
  • 作用:作为导航栏的一部分,用于包含和布局所有 Tab 选项。

四、进阶应用和实际案例

1. 高亮 Tab 和排序状态管理

在实际应用中,可能需要根据用户的操作保存和恢复排序状态。例如,在用户切换到“最新”标签后,我们可以保持这个状态,以便用户刷新页面后仍能看到上次选择的排序方式。这可以通过浏览器的本地存储(localStorage)来实现。

useEffect(() => {const savedTab = localStorage.getItem('activeTab') || 'hot';setActiveTab(savedTab);
}, []);useEffect(() => {localStorage.setItem('activeTab', activeTab);
}, [activeTab]);

2. 多条件排序

在某些复杂场景下,可能需要进行多条件排序。例如,用户可能希望首先按点赞数排序,然后再按时间排序。这种情况下,可以扩展排序逻辑以支持多条件排序。

const onToggle = type => {setActiveTab(type);let newList;if (type === 'time') {newList = orderBy(list, ['ctime', 'like'], ['desc', 'desc']);} else {newList = orderBy(list, ['like', 'ctime'], ['desc', 'desc']);}setList(newList);
};

代码源


在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 实战解读:Llama Guard 3 Prompt Guard
  • 【机器学习】探索图神经网络 (GNNs): 揭秘图结构数据处理的未来
  • 软件环境安装-通过Docker安装rabbitmq
  • 在Android开发中,如何优化onCreate()和onResume()方法以提高应用性能?
  • 破局产品同质化:解锁3D交互式营销新纪元!
  • Java 使用 POI 导出Excel,实现单元格输入内容提示功能
  • LabVIEW操作系列1
  • 使用abpcli创建项目时提示数据库迁移失败
  • uniapp开发精选短视频视频小程序实战笔记20240725,实现顶部轮播图和热门短剧
  • VulnHub靶机入门篇--Kioptrix4
  • scrapy爬取城市天气数据
  • 【Golang 面试 - 进阶题】每日 3 题(一)
  • WordPress原创插件:启用关闭经典编辑器和小工具
  • 力扣刷题----42. 接雨水
  • 【图像处理】不智能的目标识别
  • 分享一款快速APP功能测试工具
  • Android Volley源码解析
  • Android组件 - 收藏集 - 掘金
  • HTTP那些事
  • Intervention/image 图片处理扩展包的安装和使用
  • Javascripit类型转换比较那点事儿,双等号(==)
  • log4j2输出到kafka
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • nginx 负载服务器优化
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 大型网站性能监测、分析与优化常见问题QA
  • 第2章 网络文档
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 记一次删除Git记录中的大文件的过程
  • 精彩代码 vue.js
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 使用 @font-face
  • 学习使用ExpressJS 4.0中的新Router
  • Android开发者必备:推荐一款助力开发的开源APP
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​flutter 代码混淆
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #Linux(make工具和makefile文件以及makefile语法)
  • #nginx配置案例
  • $jQuery 重写Alert样式方法
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Java)【深基9.例1】选举学生会
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (全注解开发)学习Spring-MVC的第三天
  • (三分钟)速览传统边缘检测算子
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (转)JAVA中的堆栈
  • .a文件和.so文件
  • .Net 6.0--通用帮助类--FileHelper
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能