评论发布完整篇(react版)

news2024/11/28 6:36:12

        此篇文章阐述评论的最新、最热之间的tab标签切换(包括当前所在tab标签的高亮显示问题);当前评论的删除;除此之外还延伸了用户的评论实时发布功能。其中最新tab标签所展示的内容是根据当前评论点赞数来进行排序,点赞数量越多,此条评论越靠前;最新tab标签页所展示的内容是根据当前评论发布时间来进行排序,随着时间的推移,此条评论越靠前。

话不多说,上代码:

1.安装必要插件

classnamesdayjslodashnode-sasssass-loaderuuidlodash

安装命令如下:

classnames:npm install classnames或者 yarn add classnames

dayjs:npm install dayjs 或者 yarn add dayjs

lodash:npm install lodash 或者 yarn add lodash

安装scss相关包:npm install sassnpm install sass-resources-loader

uuid:npm install uuid或者 yarn add uuid

lodash:npm install lodash或者 yarn add lodash

安装好后可到package.json中查看相应版本信息

2.App.scss文件

.app {

    width:100%;

    height: 100%;

}

.reply-navigation{

    .nav-bar{

        list-style: none;

        display: flex;

        text-align: center;

        height:20px;

        line-height: 20px;

        .nav-title{

            margin-right:30px;

            .nav-title-text{

                font-size:25px;

                font-weight: 700;

            }

        }

        .nav-sort{

            color:darkgray;

            .nav-item{

                width:35px;

                cursor: pointer;

            }

            &>:first-child{

                margin-right:35px;

                border-right:2px solid darkgray;

                padding-right:35px;

            }

            .active{

                color:orange;

            }

        }

    }

}

.reply-wrap{

    height:100%;

    background: url('./images/bg.jpg') no-repeat;

    background-size: 100% 100%;

    padding:20px;

    .box-normal{

        display: flex;

        justify-content: flex-start;

        margin-bottom: 20px;

        .reply-box-avator{

            .bili-avator{

                width:80px;

                height: 80px;

                .bili-avator-img{

                    border-radius: 50%;

                    width:100%;

                    height: 100%;

                }

            }

        }

        .reply-box-wrap{

            display: flex;

            height: 80px;

            margin-left:20px;

            overflow: hidden;

            .reply-box-textarea{

                width: 400px;

                margin-top: 15px;

                height: 50px;

                line-height: 50px;

                text-align: center;

                background-color:#E5E5E5;

            }

            .reply-box-send{

                width:80px;

                height: 55px;

                line-height: 55px;

                margin-top: 15px;

                background-color: cornflowerblue;

                color:#fff;

                text-align: center;

                margin-left:15px;

                border-radius: 4px;

                cursor: pointer;

                .send-text{

                    font-size: 20px;

                    border: none;

                }

            }

        }

    }

    .reply-list{

        .reply-item{

            width:100%;

            height: 130px;

            display: flex;

            justify-content: flex-start;

            margin-top:10px;

            .root-reply-avator{

                width:5%;

                .bili-avator{

                    .bili-avator-img{

                        width:60px;

                        height:60px;

                        border-radius:50%;

                    }

                }

            }

            .content-wrap{

                width:95%;

                overflow: hidden;

                border-bottom: 2px solid darkgray;

                .user-info{

                    .user-name{

                        font-size: 16px;

                        color:darkgray;

                        font-weight: 500;

                    }

                }

                .root-reply{

                    margin-top:25px;

                    .reply-content{

                        font-size: 20px;

                        color:chocolate;

                        font-weight: 700;

                    }

                    .reply-info{

                        font-size: 14px;

                        color:darkgray;

                        font-weight: 500;

                        margin-top:15px;

                        .reply-time{

                            margin-right:25px;

                        }

                        .reply-count{

                            margin-right:25px;

                        }

                        .reply-delete{

                            cursor: pointer;

                        }

                        .reply-delete:hover{

                            color:cornflowerblue;

                        }

                    }

                }

            }

        }

    }

}

3.App.js文件

import { useRef, useState } from 'react'

import './App.scss'

import avator from './images/avator.jpg'

import _ from 'lodash'

import classNames from 'classnames'

import { v4 as uuidV4 } from 'uuid'

import dayjs from 'dayjs'

//评论列表数据

const list = [

  {

    rpid: 1, //评论id

    user: {

      //用户信息

      uid: '13258165',

      avator: 'http://toutiao.itheima.net/resources/images/9.jpg',

      uname: '周杰伦',

    },

    content: '哎呦,不错哦', //评论内容

    ctime: '10-25 12:15', //评论时间

    like: 88,

  },

  {

    rpid: 2, //评论id

    user: {

      //用户信息

      uid: '36080105',

      avator: 'http://toutiao.itheima.net/resources/images/98.jpg',

      uname: '许嵩',

    },

    content: '我寻你千百度,日出到迟暮', //评论内容

    ctime: '04-12 08:45', //评论时间

    like: 98,

  },

  {

    rpid: 3, //评论id

    user: {

      //用户信息

      uid: '30009257',

      avator: 'http://toutiao.itheima.net/resources/images/56.jpg',

      uname: '王心凌',

    },

    content: '或许失败过,但从未认输', //评论内容

    ctime: '12-18 19:02', //评论时间

    like: 120,

  },

  {

    rpid: 4, //评论id

    user: {

      //用户信息

      uid: '19858625',

      avator: 'http://toutiao.itheima.net/resources/images/67.jpg',

      uname: '徐凯',

    },

    content: '没有永远的敌人', //评论内容

    ctime: '11-20 20:15', //评论时间

    like: 120,

  },

  {

    rpid: 5, //评论id

    user: {

      //用户信息

      uid: '30009257',

      avator: 'http://toutiao.itheima.net/resources/images/37.jpg',

      uname: '杨幂',

    },

    content: '不只玫瑰有爱意', //评论内容

    ctime: '07-20 20:15', //评论时间

    like: 456,

  },

  {

    rpid: 6, //评论id

    user: {

      //用户信息

      uid: '30009257',

      avator: 'http://toutiao.itheima.net/resources/images/28.jpg',

      uname: '徐良',

    },

    content: '女骑士', //评论内容

    ctime: '03-14 20:15', //评论时间

    like: 253,

  },

]

//当前登录用户信息

const user = {

  //用户id

  uid: '30009257',

  //用户头像

  avator,

  //用户昵称

  uname: '徐凯工作室',

}

//导航tab数组

const tabs = [

  { type: 'hot', text: '最热' },

  { type: 'time', text: '最新' },

]

const App = () => {

  const [commentList, setCommentList] = useState(list)

  //删除事件

  const deleteHandle = (id) => {

    //根据id删除

    setCommentList(commentList.filter((item) => item.rpid !== id))

    console.log(id)

  }

  //存储type

  const [type, setType] = useState('hot')

  //tabs标签切换事件,根据 type切换

  const typeHandlerChange = (type) => {

    setType(type)

    console.log(type, '切换tab项')

    if (type === 'time') {

      //允许在集合commentList中,指定迭代函数ctime进行倒序排序desc

      setCommentList(_.orderBy(commentList, 'ctime', 'desc'))

    } else {

      //允许在集合commentList中,指定迭代函数like进行倒序排序desc

      setCommentList(_.orderBy(commentList, 'like', 'desc'))

    }

  }

  const [content, setContent] = useState('')

  const inputRef = useRef(null)

  const sendHandler = () => {

    setCommentList([

      ...commentList,

      {

        rpid: uuidV4(), //唯一识别id,通过uuid生成器产生随机id

        user: {

          //用户信息

          uid: '30009257',

          avator: 'http://toutiao.itheima.net/resources/images/28.jpg',

          uname: '徐良',

        },

        content: content, //评论内容

        ctime: dayjs(new Date()).format('MM-DD hh:mm'), //格式化 月-日 时:分

        like: 253,

      },

    ])

    setContent('') //清空输入框内的值

    inputRef.current.focus() //再次聚焦输入框

    console.dir(inputRef.current)

  }

  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>

          {/* 高亮类名:active */}

          <li className="nav-sort">

            {tabs.map((item) => (

              <span

                className={classNames('nav-item', {

                  active: type === item.type,

                })}

                key={item.type}

                onClick={() => typeHandlerChange(item.type)}

              >

                {item.text}

              </span>

            ))}

          </li>

        </ul>

      </div>

      <div className="reply-wrap">

        {/*  发表评论 */}

        <div className="box-normal">

          {/*  当前用户头像 */}

          <div className="reply-box-avator">

            <div className="bili-avator">

              <img

                className="bili-avator-img"

                alt="用户头像"

                src={user.avator}

              />

            </div>

          </div>

          <div className="reply-box-wrap">

            {/* 评论框 */}

            <textarea

              className="reply-box-textarea"

              placeholder="发一条友善的评论"

              value={content}

              onChange={(e) => {

                setContent(e.target.value)

              }}

              ref={inputRef}

            ></textarea>

            {/* 发布按钮 */}

            <div className="reply-box-send">

              <div className="send-text" onClick={sendHandler}>

                发布

              </div>

            </div>

          </div>

        </div>

        {/*  评论列表 */}

        <div className="reply-list">

          {/*  评论项 */}

          {commentList.map((item) => (

            <div className="reply-item" key={item.rpid}>

              {/*头像 */}

              <div className="root-reply-avator">

                <div className="bili-avator">

                  <img

                    className="bili-avator-img"

                    alt=""

                    src={item.user.avator}

                  />

                </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-count">点赞数:{item.like}</span>

                    {/*删除 */}

                    {/*删除条件 */}

                    {user.uid === item.user.uid && (

                      <span

                        className="reply-delete"

                        onClick={() => {

                          deleteHandle(item.rpid)

                        }}

                      >

                        {'删除'}

                      </span>

                    )}

                  </div>

                </div>

              </div>

            </div>

          ))}

        </div>

      </div>

    </div>

  )

}

export default App

结果展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1581933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字社会下的智慧公厕:构筑智慧城市的重要组成部分

智慧城市已经成为现代城市发展的趋势&#xff0c;而其中的数字化转型更是推动未来社会治理体系和治理能力现代化的必然要求。在智慧城市建设中&#xff0c;智慧公厕作为一种新形态的信息化公共厕所&#xff0c;扮演着重要角色。本文智慧公厕源头实力厂家广州中期科技有限公司&a…

Go gin框架(详细版)

目录 0. 为什么会有Go 1. 环境搭建 2. 单-请求&&返回-样例 3. RESTful API 3.1 首先什么是RESTful API 3.2 Gin框架支持RESTful API的开发 4. 返回前端代码 go.main index.html 5. 添加静态文件 main.go 改动的地方 index.html 改动的地方 style.css 改动…

C语言 | 字符函数和字符串函数

目录&#xff1a; 1. 字符分类函数 2. 字符转换函数 3. strlen的使用和模拟实现 4. strcpy的使用和模拟实现 5. strcat的使用和模拟实现 6. strcmp的使用和模拟实现 7. strncpy函数的使用 8. strncat函数的使用 9. strncmp函数的使用 10. strstr的使用 11. strtok函…

力扣121. 买卖股票的最佳时机

Problem: 121. 买卖股票的最佳时机 文章目录 题目描述思路复杂度Code 题目描述 思路 1.定义一个int数组max大小同prices&#xff1b;定义int变量curMax初始化为0&#xff1b; 2.从后往前遍历数组&#xff0c;若当前元素prices[i] > curMax时&#xff0c;则使将其赋值给curMa…

医院预约系统微信小程序APP前后端

医院预约系统具体功能介绍&#xff1a;展示信息、可以注册和登录&#xff0c; 预约&#xff08;包含各个科室的预约&#xff0c;可以预约每个各个医生&#xff09;&#xff0c;就诊引导包含预约的具体信息&#xff0c;包含就诊时间、就诊科室、就诊医生以及就诊人信息、和支付状…

如何注册midjourney账号

注册Midjourney账号比较简单&#xff0c;准备好上网工具&#xff0c;进入官网 Midjourney访问地址&#xff1a; https://www.midjourney.com/ 目前没有免费使用额度了&#xff0c;会员最低 10 美元/月&#xff0c;一般建议使用30美元/月的订阅方案。了解如何订阅可以查看订阅…

MyBatis源码介绍

文章目录 MyBatis的核心流程介绍SqlSessionFactory的理解MyBatis中的Executor的源码理解Spring中是如何解决MySQL的SqlSession的线程安全问题MyBatis面向Mapper编程工作原理Mybatis动态sql执行原理Mybatis的一级、二级缓存实现原理Mybatis的插件运行原理以及如何编写一个插件my…

019——IIC模块驱动开发(基于EEPROM【AT24C02】和I.MX6uLL)

目录 一、 IIC基础知识 二、Linux中的IIC&#xff08;韦东山老师的学习笔记&#xff09; 1. I2C驱动程序的层次 2. I2C总线-设备-驱动模型 2.1 i2c_driver 2.2 i2c_client 三、 AT24C02 介绍 四、 AT24C02驱动开发 实验 驱动程序 应用程序 一、 IIC基础知识 总线类…

【linux】谈MobaXterm支持的连接方式

目前远程联机服务器主要有文字命令行接口和图形界面接口两种。 一、命令行接口方式 1.1 加密传输-SSH SSH为主&#xff0c;目前大多在网络上的数据封包都是加密的技术&#xff0c;等到传输的封包加密后再传输到网络上&#xff0c;以增加数据在Internet上面传送的安全性 1.2…

【软考】哈希表

目录 一、概念1.1 定义 二、哈希函数的构造方法2.1 说明2.2 特性 三、处理冲突的方法3.1 说明3.2 开放定址法3.2.1 说明3.2.2 线性探测 3.3 链地址法3.4 再哈希法3.5 建立公共溢出区 四、哈希表的查找4.1 查找过程4.2 查找特点4.3 装填因子 一、概念 1.1 定义 1.一般存储结构由…

Solid Converter 10.1下载地址及安装教程

Solid Converter 10是一款专业的PDF转换工具&#xff0c;用于将PDF文件转换为可编辑的文档格式&#xff0c;如Word、Excel、PowerPoint等。它提供了强大的转换功能和一系列实用的工具&#xff0c;帮助用户将PDF内容转换为可重复使用和编辑的格式。 Solid Converter 10的主要功…

vcruntime140.dll文件缺失的多种解决方法,这五种修复vcruntime140.dll绝对有效

当你在使用电脑的时候&#xff0c;可能会遇到一个提示错误&#xff0c;显示“vcruntime140.dll文件缺失&#xff0c;程序因此无法启动”。这种状况不但打断了你的日常使用&#xff0c;还可能对你的工作效率造成不利影响。为了助你更好地搞清楚这个问题的由来以及解决方案&#…

贪心算法|860.柠檬水找零

力扣题目链接 class Solution { public:bool lemonadeChange(vector<int>& bills) {int five 0, ten 0, twenty 0;for (int bill : bills) {// 情况一if (bill 5) five;// 情况二if (bill 10) {if (five < 0) return false;ten;five--;}// 情况三if (bill …

基于java+springboot+vue实现的人事管理系统(文末源码+Lw)23-242

摘 要 使用旧方法对人事管理系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在人事管理系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的人事管理…

【C++】探索C++中的类与对象(下)---深入理解C++中的关键概念与应用

​​ &#x1f331;博客主页&#xff1a;青竹雾色间. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 在C编程中&#xff0c;有许多重要的概念和特性&#xff0c;包括构造函数、explicit关键字、静态成员、友元以及内部类…

【Web世界探险家】CSS美学(一)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

linux 迁移home目录以及修改conda中pip的目录,修改pip安装路径

1&#xff09;sudo rsync -av /home/lrf /data/home/lrf 将/home目录下的文件进行复制&#xff08;假设机械硬盘挂载在/data目录下&#xff09;** 2&#xff09;usermod -d /data/home/lrf -m lrf 修改用户$HOME变量** 3&#xff09;vi /etc/passwd 查看对应用户的$HOME变量是…

IDEA无法成功配置Tomcat的解决方法(IDEA版本问题)

在创建Servlet时&#xff0c;下载了Tomcat文件夹以及成功配置了环境变量之后&#xff0c;在IDEA中怎么都找不到Tomcat&#xff0c;尝试了网络中的各种方法&#xff0c;都不行&#xff0c;结果发现时IDEA版本的问题。因为我下的IDEA是社区版的&#xff0c;所以没有自带的Tomcat&…

【HTML】简单制作一个3D动态粒子效果的时空隧道

目录 前言 开始 HTML部分 CSS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段HTML&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建两个文本文档&#xff0c;其中HTML的文件名改为[index.html]&#xff0c;CSS的文件名改为[Bab…