当前位置:   article > 正文

基于React实现B站评论区

基于React实现B站评论区

        今天继续来学习一下React,使用React实现B站评论区,如下图:

        在使用React开发类似B站评论区的功能时,我们需要考虑以下几个关键点来构建一个基本的评论系统:

1. 设计组件结构

首先,设计组件结构是关键。至少需要以下几种组件:

  • CommentList: 负责展示评论列表。
  • Comment: 单个评论项的展示,包括用户名、评论内容、时间戳等。
  • CommentContent: 用户输入评论的内容,包括文本输入框和提交按钮。
  • User: 当前的登录的用户
  • TabList: 评论排序的导航类型

2. 管理状态

        使用React的状态管理功能(如useState或useReducer)来处理评论数据和表单输入状态。例如,可以创建一个状态来存储所有的评论数据,以及一个状态来管理评论表单的输入值。

3. 发送和获取评论

当然,本次实现不考虑连接后端,只利用假的数据来实现B站评论区的按照热度、事件排序展示、删除评论、发布评论。如果需要连接后端可以考虑下面你的操作:

获取评论:  如果评论数据来自后端API,可以使用fetch或第三方库如axios来获取数据,并在组件挂载时或根据需要触发请求。
发送评论: 当用户提交评论时,捕获表单数据并发送POST请求到后端API,成功后通常会刷新评论列表以显示新评论。
删除评论:当用户删除评论的时候,捕获评论Id并发送DELETE请求到后端API,后端根据ID删除该条评论。

4. 代码实现

  1. import './App.scss'
  2. import {useState} from "react";
  3. import avatar1 from './images/1.png';
  4. import avatar2 from './images/2.png';
  5. import stukk from './images/lyy.jpg';
  6. /**
  7. * 评论列表的渲染和操作
  8. *
  9. * 1. 根据状态渲染评论列表
  10. * 2. 删除评论
  11. * 3. 发布评论
  12. */
  13. // 评论列表数据
  14. const defaultList = [
  15. {
  16. // 评论id
  17. rpid: 3,
  18. // 用户信息
  19. user: {
  20. uid: '13258165',
  21. avatar: avatar1,
  22. uname: '周杰伦',
  23. },
  24. // 评论内容
  25. content: '哎哟,不错哦',
  26. // 评论时间
  27. ctime: '10-18 08:15',
  28. like: 98,
  29. },
  30. {
  31. rpid: 2,
  32. user: {
  33. uid: '36080105',
  34. avatar: avatar2,
  35. uname: '许嵩',
  36. },
  37. content: '我寻你千百度 日出到迟暮',
  38. ctime: '11-13 11:29',
  39. like: 88,
  40. },
  41. {
  42. rpid: 1,
  43. user: {
  44. uid: '30009257',
  45. avatar: stukk,
  46. uname: 'stu_kk',
  47. },
  48. content: '关注stu_kk',
  49. ctime: '10-19 09:00',
  50. like: 66,
  51. },
  52. ]
  53. // 当前登录用户信息
  54. const user = {
  55. // 用户id
  56. uid: '30009257',
  57. // 用户头像
  58. avatar: stukk,
  59. // 用户昵称
  60. uname: 'stu_kk',
  61. }
  62. /**
  63. * 导航 Tab 的渲染和操作
  64. *
  65. * 1. 渲染导航 Tab 和高亮
  66. * 2. 评论列表排序
  67. * 最热 => 喜欢数量降序
  68. * 最新 => 创建时间降序
  69. */
  70. // 导航 Tab 数组
  71. const tabs = [
  72. {type: 'hot', text: '最热', isActive: true},
  73. {type: 'time', text: '最新', isActive: false},
  74. ]
  75. const App = () => {
  76. const [commentList, setCommentList] = useState(defaultList); // 评论列表
  77. const [tabList, setTabList] = useState(tabs); // 导航 Tab 数组
  78. const [commentContent, setCommentContent] = useState(''); // 评论内容
  79. const changeTabList = (id) => { //改变导航Tab
  80. const newTabList = tabList.map((item, index) => {
  81. if (index === id) {
  82. item.isActive = true;
  83. } else {
  84. item.isActive = false;
  85. }
  86. return item;
  87. });
  88. return newTabList;
  89. }
  90. const clickTab = (id) => { // 点击导航Tab
  91. const newCommentList = id === 0 ? commentList.sort((a, b) => b.like - a.like) : commentList.sort((a, b) => (
  92. b.ctime > a.ctime ? 1 : -1
  93. ));
  94. console.log(newCommentList)
  95. setCommentList(newCommentList);
  96. setTabList(changeTabList(id));
  97. }
  98. const sendComment = () => { //发布评论
  99. console.log(111)
  100. if (commentContent.trim() === '') {
  101. alert('评论内容不能为空');
  102. return;
  103. }
  104. const newCommentList = [
  105. {
  106. rpid: commentList.length + 1,
  107. user: user,
  108. content: commentContent,
  109. ctime: '12-19 09:00',
  110. like: 0,
  111. },
  112. ...commentList,
  113. ];
  114. setCommentList(newCommentList);
  115. setCommentContent('');
  116. }
  117. const deleteCommentById = (id) => { //根据Id删除自己的评论
  118. setCommentList(commentList.filter((item) => item.rpid !== id))
  119. }
  120. return (
  121. <div className="app">
  122. {/* 导航 Tab */}
  123. <div className="reply-navigation">
  124. <ul className="nav-bar">
  125. <li className="nav-title">
  126. <span className="nav-title-text">评论</span>
  127. {/* 评论数量 */}
  128. <span className="total-reply">{10}</span>
  129. </li>
  130. <li className="nav-sort">
  131. {/* 高亮类名: active */}
  132. {tabList.map((item,index) => (
  133. <span onClick={()=>clickTab(index)} className={item.isActive ? 'nav-item active' : 'nav-item'} key={item.type}>{item.text}</span>
  134. ))}
  135. </li>
  136. </ul>
  137. </div>
  138. <div className="reply-wrap">
  139. {/* 发表评论 */}
  140. <div className="box-normal">
  141. {/* 当前用户头像 */}
  142. <div className="reply-box-avatar">
  143. <div className="bili-avatar">
  144. <img className="bili-avatar-img" src={user.avatar} alt="用户头像"/>
  145. </div>
  146. </div>
  147. <div className="reply-box-wrap">
  148. {/* 评论框 */}
  149. <textarea
  150. className="reply-box-textarea"
  151. placeholder="发一条友善的评论"
  152. value={commentContent}
  153. onChange={(e) => setCommentContent(e.target.value)}
  154. />
  155. {/* 发布按钮 */}
  156. <div className="reply-box-send" onClick={sendComment}>
  157. <div className="send-text" >发布</div>
  158. </div>
  159. </div>
  160. </div>
  161. {/* 评论列表 */}
  162. <div className="reply-list">
  163. {/* 评论项 */}
  164. {commentList.map(item => (
  165. <div className="reply-item" key={item.rpid}>
  166. {/* 头像 */}
  167. <div className="root-reply-avatar">
  168. <div className="bili-avatar">
  169. <img
  170. className="bili-avatar-img"
  171. alt=""
  172. src={item.user.avatar}
  173. />
  174. </div>
  175. </div>
  176. <div className="content-wrap">
  177. {/* 用户名 */}
  178. <div className="user-info">
  179. <div className="user-name">{item.user.uname}</div>
  180. </div>
  181. {/* 评论内容 */}
  182. <div className="root-reply">
  183. <span className="reply-content">{item.content}</span>
  184. <div className="reply-info">
  185. {/* 评论时间 */}
  186. <span className="reply-time">{item.ctime}</span>
  187. {/* 评论数量 */}
  188. <span className="reply-time">点赞数:{item.like}</span>
  189. {/*根据用户与当前用户对比,设置是否有权限删除*/}
  190. {item.user.uid === user.uid && <span className="delete-btn" onClick={() => deleteCommentById(item.rpid)}>删除</span> }
  191. </div>
  192. </div>
  193. </div>
  194. </div>
  195. ))}
  196. </div>
  197. </div>
  198. </div>
  199. )
  200. }
  201. export default App

5. 实现效果

6. 代码解释

        上面React代码实现了一个基础的评论区功能,包含评论列表的渲染、导航Tab切换(用于排序)、发布评论、以及删除自己的评论功能。下面是对代码的详细解析:
1. 数据初始化
        评论列表数据 (defaultList): 定义了初始的评论数据数组,每个评论对象包含了评论ID (rpid)、用户信息 (user)、评论内容 (content)、评论时间 (ctime) 和点赞数 (like)。
当前登录用户信息 (user): 包含用户ID、头像和用户名,用于识别和执行删除操作。
2. 状态管理

  • 使用 useState Hook 来管理组件状态:
  • commentList: 当前的评论列表。
  • tabList: 导航Tab的状态,包括类型、文本和是否激活。
  • commentContent: 用户在评论框中输入的内容。

3. 导航Tab功能

  • tabs: 定义了两个导航Tab选项:“最热”和“最新”,每个Tab都有一个类型 (type)、文本 (text) 和激活状态 (isActive)。
  • changeTabList: 函数用来改变Tab的激活状态。
  • clickTab: 处理Tab点击事件,根据选择的Tab类型对评论列表进行排序,并更新Tab的激活状态。

4. 发布评论
        sendComment: 用户点击“发布”按钮时调用此函数,检查评论内容是否为空,然后将新评论追加到评论列表的开头,并清空输入框。
5. 删除评论
        deleteCommentById: 根据评论ID从评论列表中删除对应的评论,仅允许用户删除自己发布的评论。
6. UI渲染

  • 导航Tab (reply-navigation): 渲染导航Tab,根据tabList的状态来决定哪个Tab被高亮显示。
  • 评论输入框和发布按钮: 用户可以在此输入评论内容并发布。
  • 评论列表 (reply-list): 根据commentList渲染评论项,每个评论项包含用户头像、用户名、评论内容、评论时间和删除按钮(如果当前登录用户是评论作者)。

7. 总结

        文章使用React构建了一个仿照B站基本的前端评论系统,实现了动态加载、排序、添加和删除评论的基本功能。通过React的状态管理和事件处理机制,实现了交互式的用户体验。但是在实际应用中,还需考虑与后端接口的交互、错误处理、分页加载、以及更复杂的用户交互逻辑。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/545489
推荐阅读
相关标签
  

闽ICP备14008679号