文章目录
-
- 一、基本概念和初始化
- 二、切换与排序功能的实现
-
- [1. 函数定义和参数](#1. 函数定义和参数)
- [2. 设置活动 Tab](#2. 设置活动 Tab)
- [3. 定义新列表变量](#3. 定义新列表变量)
- [4. 根据排序类型处理列表](#4. 根据排序类型处理列表)
-
- [4.1 按时间降序排序](#4.1 按时间降序排序)
- [4.2 按点赞数降序排序](#4.2 按点赞数降序排序)
- [5. 更新评论列表](#5. 更新评论列表)
- [三、渲染导航 Tab 和评论列表](#三、渲染导航 Tab 和评论列表)
-
- [1. `map` 方法](#1.
map
方法) - [2. `key` 属性](#2.
key
属性) - [3. `className` 动态赋值](#3.
className
动态赋值) - [4. `onClick` 事件处理器](#4.
onClick
事件处理器) - [5. `item.text`](#5.
item.text
) - [6. `<li>` 容器](#6.
<li>
容器)
- [1. `map` 方法](#1.
- 四、进阶应用和实际案例
-
- [1. 高亮 Tab 和排序状态管理](#1. 高亮 Tab 和排序状态管理)
- [2. 多条件排序](#2. 多条件排序)
在现代网页应用中,评论列表是常见的功能模块。为了提高用户体验,我们经常需要对评论进行排序和筛选,以便用户能够更方便地找到感兴趣的内容。本文将深入探讨如何在 React 应用中实现"最新"和"最热"切换与排序功能,涵盖其基本用法、进阶应用以及实际案例。通过本文,你将全面了解如何在 React 应用中有效地实现评论排序功能,并灵活应用于实际项目中。
一、基本概念和初始化
评论数据和用户信息
首先,我们需要一些初始化的数据来展示评论列表。在下面的代码中,我们定义了一个包含评论数据的列表 defaultList
和一个模拟的当前用户 user
。
js
// 评论列表数据
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):最热 和 最新。用户可以通过点击这两个选项卡来切换评论的排序方式。
js
// 导航 Tab 数组
const tabs = [
{ type: 'hot', text: '最热' },
{ type: 'time', text: '最新' },
];
使用 useState
来管理当前选中的 Tab,并通过点击事件更新状态。onToggle
函数用于处理 Tab 的切换逻辑,并对评论列表进行相应的排序。
js
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
库)根据传入的排序字段(如 ctime
或 like
)和排序顺序(降序)对评论列表进行排序,并更新状态。
1. 函数定义和参数
onToggle
是一个函数,接收一个参数 type
,用于指定当前选中的排序类型。这个 type
参数可以是 'time'
或 'hot'
,分别代表"最新"和"最热"两种排序方式。
2. 设置活动 Tab
js
setActiveTab(type);
- 功能 :调用
setActiveTab
函数来更新当前活动的 Tab。 - 作用 :更新组件的状态,使得用户界面能够反映当前选中的排序方式。例如,如果用户点击了"最新"Tab,
setActiveTab
会将activeTab
的值更新为'time'
,从而使得"最新"Tab 高亮显示。
3. 定义新列表变量
js
let newList;
- 功能 :声明一个变量
newList
,用于存储排序后的评论列表。 - 作用 :这个变量将在根据
type
排序评论列表后被赋值。
4. 根据排序类型处理列表
4.1 按时间降序排序
js
if (type === 'time') {
// 按时间降序排序
newList = orderBy(list, 'ctime', 'desc');
}
- 功能 :检查
type
是否为'time'
。 - 作用 :如果是
'time'
,则使用orderBy
函数对list
(评论列表)按ctime
(评论时间)进行降序排序。orderBy
是lodash
库中的一个函数,允许指定排序字段和排序顺序。 - 具体操作:
list
是待排序的数组。'ctime'
是排序字段,即按照评论时间排序。'desc'
指定排序顺序为降序。
4.2 按点赞数降序排序
js
else {
// 按点赞数降序排序
newList = orderBy(list, 'like', 'desc');
}
- 功能 :如果
type
不是'time'
,则认为排序方式是按点赞数排序。 - 作用 :使用
orderBy
函数对list
按like
(点赞数)进行降序排序。 - 具体操作:
list
是待排序的数组。'like'
是排序字段,即按照点赞数排序。'desc'
指定排序顺序为降序。
5. 更新评论列表
js
setList(newList);
- 功能 :调用
setList
函数来更新组件状态中的评论列表。 - 作用 :将排序后的
newList
更新到组件状态中,从而使得评论列表的显示顺序根据用户的选择进行更新。
三、渲染导航 Tab 和评论列表
在组件的返回 JSX 中,渲染了 Tab 切换按钮和评论列表。点击 Tab 按钮会触发 onToggle
函数,更新排序方式。
js
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 => (
<div
key={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
属性
js
key={item.type}
- 功能 :
key
属性用于标识数组中每个元素的唯一性,以便 React 能够高效地更新和渲染列表。 - 作用 :这里使用
item.type
作为每个<div>
元素的key
,因为type
是唯一的('hot'
或'time'
)。
3. className
动态赋值
js
className={item.type === activeTab ? 'nav-item active' : 'nav-item'}
- 功能 :根据当前活动的 Tab (
activeTab
) 动态设置<div>
元素的className
。 - 作用 :如果当前
item.type
等于activeTab
,则为该<div>
元素添加nav-item active
类,使其显示为活动状态(高亮)。否则,仅添加nav-item
类。
4. onClick
事件处理器
js
onClick={() => onToggle(item.type)}
- 功能 :为
<div>
元素添加onClick
事件处理器。 - 作用 :当用户点击某个 Tab 时,调用
onToggle
函数,并将当前item.type
作为参数传递给onToggle
函数,从而触发排序逻辑的切换。
5. item.text
js
{item.text}
- 功能 :在每个
<div>
元素内显示item.text
的内容。 - 作用:显示 Tab 文本,分别为"最热"和"最新"。
6. <li>
容器
js
<li className="nav-sort">
...
</li>
- 功能 :将所有生成的
<div>
元素包含在一个<li>
元素内,并为其添加nav-sort
类。 - 作用:作为导航栏的一部分,用于包含和布局所有 Tab 选项。
四、进阶应用和实际案例
1. 高亮 Tab 和排序状态管理
在实际应用中,可能需要根据用户的操作保存和恢复排序状态。例如,在用户切换到"最新"标签后,我们可以保持这个状态,以便用户刷新页面后仍能看到上次选择的排序方式。这可以通过浏览器的本地存储(localStorage)来实现。
js
useEffect(() => {
const savedTab = localStorage.getItem('activeTab') || 'hot';
setActiveTab(savedTab);
}, []);
useEffect(() => {
localStorage.setItem('activeTab', activeTab);
}, [activeTab]);
2. 多条件排序
在某些复杂场景下,可能需要进行多条件排序。例如,用户可能希望首先按点赞数排序,然后再按时间排序。这种情况下,可以扩展排序逻辑以支持多条件排序。
js
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);
};