赞
踩
今天继续来学习一下React,使用React实现B站评论区,如下图:
在使用React开发类似B站评论区的功能时,我们需要考虑以下几个关键点来构建一个基本的评论系统:
首先,设计组件结构是关键。至少需要以下几种组件:
使用React的状态管理功能(如useState或useReducer)来处理评论数据和表单输入状态。例如,可以创建一个状态来存储所有的评论数据,以及一个状态来管理评论表单的输入值。
当然,本次实现不考虑连接后端,只利用假的数据来实现B站评论区的按照热度、事件排序展示、删除评论、发布评论。如果需要连接后端可以考虑下面你的操作:
获取评论: 如果评论数据来自后端API,可以使用fetch或第三方库如axios来获取数据,并在组件挂载时或根据需要触发请求。
发送评论: 当用户提交评论时,捕获表单数据并发送POST请求到后端API,成功后通常会刷新评论列表以显示新评论。
删除评论:当用户删除评论的时候,捕获评论Id并发送DELETE请求到后端API,后端根据ID删除该条评论。
- import './App.scss'
- import {useState} from "react";
- import avatar1 from './images/1.png';
- import avatar2 from './images/2.png';
- import stukk from './images/lyy.jpg';
-
- /**
- * 评论列表的渲染和操作
- *
- * 1. 根据状态渲染评论列表
- * 2. 删除评论
- * 3. 发布评论
- */
-
- // 评论列表数据
- const defaultList = [
- {
- // 评论id
- rpid: 3,
- // 用户信息
- user: {
- uid: '13258165',
- avatar: avatar1,
- uname: '周杰伦',
- },
- // 评论内容
- content: '哎哟,不错哦',
- // 评论时间
- ctime: '10-18 08:15',
- like: 98,
- },
- {
- rpid: 2,
- user: {
- uid: '36080105',
- avatar: avatar2,
- uname: '许嵩',
- },
- content: '我寻你千百度 日出到迟暮',
- ctime: '11-13 11:29',
- like: 88,
- },
- {
- rpid: 1,
- user: {
- uid: '30009257',
- avatar: stukk,
- uname: 'stu_kk',
- },
- content: '关注stu_kk',
- ctime: '10-19 09:00',
- like: 66,
- },
- ]
- // 当前登录用户信息
- const user = {
- // 用户id
- uid: '30009257',
- // 用户头像
- avatar: stukk,
- // 用户昵称
- uname: 'stu_kk',
- }
-
-
- /**
- * 导航 Tab 的渲染和操作
- *
- * 1. 渲染导航 Tab 和高亮
- * 2. 评论列表排序
- * 最热 => 喜欢数量降序
- * 最新 => 创建时间降序
- */
-
- // 导航 Tab 数组
- const tabs = [
- {type: 'hot', text: '最热', isActive: true},
- {type: 'time', text: '最新', isActive: false},
- ]
-
- const App = () => {
- const [commentList, setCommentList] = useState(defaultList); // 评论列表
- const [tabList, setTabList] = useState(tabs); // 导航 Tab 数组
- const [commentContent, setCommentContent] = useState(''); // 评论内容
- const changeTabList = (id) => { //改变导航Tab
- const newTabList = tabList.map((item, index) => {
- if (index === id) {
- item.isActive = true;
- } else {
- item.isActive = false;
- }
- return item;
- });
- return newTabList;
- }
-
- const clickTab = (id) => { // 点击导航Tab
- const newCommentList = id === 0 ? commentList.sort((a, b) => b.like - a.like) : commentList.sort((a, b) => (
- b.ctime > a.ctime ? 1 : -1
- ));
- console.log(newCommentList)
- setCommentList(newCommentList);
- setTabList(changeTabList(id));
- }
-
- const sendComment = () => { //发布评论
- console.log(111)
- if (commentContent.trim() === '') {
- alert('评论内容不能为空');
- return;
- }
- const newCommentList = [
- {
- rpid: commentList.length + 1,
- user: user,
- content: commentContent,
- ctime: '12-19 09:00',
- like: 0,
- },
- ...commentList,
- ];
- setCommentList(newCommentList);
- setCommentContent('');
- }
-
- const deleteCommentById = (id) => { //根据Id删除自己的评论
- setCommentList(commentList.filter((item) => item.rpid !== id))
- }
-
- 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">{10}</span>
- </li>
- <li className="nav-sort">
- {/* 高亮类名: active */}
- {tabList.map((item,index) => (
- <span onClick={()=>clickTab(index)} className={item.isActive ? 'nav-item active' : 'nav-item'} key={item.type}>{item.text}</span>
- ))}
- </li>
- </ul>
- </div>
-
- <div className="reply-wrap">
- {/* 发表评论 */}
- <div className="box-normal">
- {/* 当前用户头像 */}
- <div className="reply-box-avatar">
- <div className="bili-avatar">
- <img className="bili-avatar-img" src={user.avatar} alt="用户头像"/>
- </div>
- </div>
- <div className="reply-box-wrap">
- {/* 评论框 */}
- <textarea
- className="reply-box-textarea"
- placeholder="发一条友善的评论"
- value={commentContent}
- onChange={(e) => setCommentContent(e.target.value)}
- />
- {/* 发布按钮 */}
- <div className="reply-box-send" onClick={sendComment}>
- <div className="send-text" >发布</div>
- </div>
- </div>
- </div>
- {/* 评论列表 */}
- <div className="reply-list">
- {/* 评论项 */}
- {commentList.map(item => (
- <div className="reply-item" key={item.rpid}>
- {/* 头像 */}
- <div className="root-reply-avatar">
- <div className="bili-avatar">
- <img
- className="bili-avatar-img"
- alt=""
- src={item.user.avatar}
- />
- </div>
- </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>
- {/*根据用户与当前用户对比,设置是否有权限删除*/}
- {item.user.uid === user.uid && <span className="delete-btn" onClick={() => deleteCommentById(item.rpid)}>删除</span> }
- </div>
- </div>
- </div>
- </div>
- ))}
- </div>
- </div>
- </div>
- )
- }
-
- export default App

上面React代码实现了一个基础的评论区功能,包含评论列表的渲染、导航Tab切换(用于排序)、发布评论、以及删除自己的评论功能。下面是对代码的详细解析:
1. 数据初始化
评论列表数据 (defaultList): 定义了初始的评论数据数组,每个评论对象包含了评论ID (rpid)、用户信息 (user)、评论内容 (content)、评论时间 (ctime) 和点赞数 (like)。
当前登录用户信息 (user): 包含用户ID、头像和用户名,用于识别和执行删除操作。
2. 状态管理
3. 导航Tab功能
4. 发布评论
sendComment: 用户点击“发布”按钮时调用此函数,检查评论内容是否为空,然后将新评论追加到评论列表的开头,并清空输入框。
5. 删除评论
deleteCommentById: 根据评论ID从评论列表中删除对应的评论,仅允许用户删除自己发布的评论。
6. UI渲染
文章使用React构建了一个仿照B站基本的前端评论系统,实现了动态加载、排序、添加和删除评论的基本功能。通过React的状态管理和事件处理机制,实现了交互式的用户体验。但是在实际应用中,还需考虑与后端接口的交互、错误处理、分页加载、以及更复杂的用户交互逻辑。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。