[uniapp] uni-ui+vue3.2小程序评论列表组件 回复评论 点赞和删除

先看效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

下载地址

uni-app官方插件市场: cc-comment组件

环境

基于vue3.2和uni-ui开发;
依赖版本参考如下:

    "dependencies": {
    "@dcloudio/uni-mp-weixin": "3.0.0-3090820231124001",
    "@dcloudio/uni-ui": "^1.4.28",
    "uni-ui": "^1.0.0",
    "vue": "^3.2.45"
  },
 "devDependencies": {
    "vite": "4.0.3"
  }
}

小程序调试基础库: 3.3.0

场景

即拿即用, 组件有详细注释内容, 方便二次开发;
目前仅在小程序使用, 其他平台能否使用请评论留言反馈谢谢, 祝大家使用愉快.

附言

主要是插件市场没找到满意的, 诸多用着也不顺, 所以有了cc-comment, 如有Bug请留言或Email, 开源不易且用且珍惜, 感谢使用.
关于功能样式, 主打一个借鉴如下;
参考[小红书]App的评论回复功能: 点击评论内容展示回复弹窗, 二级评论默认显示一条, 点击展开查看更多, 无评论收起功能.
参考[什么值得买]App的多层级回复评论title显示效果

功能

已实现
  • 无评论显示场景 √
  • 显示评论数量(新增和删除动态更新数量) √
  • 发起新评论 √
  • 点击评论内容回复 √
  • 回复一级评论 √
  • 回复二级评论 √
  • 展开二级评论 √
  • 展开超长评论内容 √
  • 不能回复自身评论 √
  • 删除 √
  • 仅可删除自身评论 √
  • 可选三类删除模式 √
  • 点赞 √
  • 点赞大于100显示99+ √
待实现
  • 图片上传 ×

有其他需求的评论区留言

:props 属性

属性名说明类型默认值必填说明
ref实例Object-true
tableData评论列表Array[ ]true
tableTotal评论总数Number0true
deleteMode评论删除模式Stringallfalsebind-当被删除的一级评论存在回复评论, 那么该评论内容变更显示为[当前评论内容已被移除] only-仅删除当前评论(后端删除相关联的回复评论, 否则总数显示不对) all-删除所有评论包括回复评论

deleteMode

@event 事件

属性名说明参数说明
likeClick点赞事件{{params},callback}{ params: 评论id }, callback回调函数, 请求后端接口后调用, 执行后续逻辑
replyClick回复事件{{params},callback}{ params:评论参数 }, callback回调函数, 请求后端接口后调用, 执行后续逻辑
deleteClick删除事件{{params,mode},callback}{ params: 评论数组id, mode:删除模式[all,bind,only] }, callback回调函数, 请求后端接口后调用, 执行后续逻辑

$ref 实例可调用属性&事件

属性名说明回调参数说明平台差异说明
newCommentFun发起新评论-event-

数据说明

// 用户信息
type userInfoKeys = {
      id: number // 用户id
      user_name: string // 用户名
      user_avatar: string // 用户头像地址
}
// 评论表
type tableDataKeys = {
      id: number // 评论id
      parent_id: number // 父级评论id
      reply_id: number // 被回复人评论id
      reply_name: string // 被回复人名称
      user_name: string // 用户名
      user_avatar: string // 评论者头像地址
      user_content: string // 评论内容
      is_like: boolean // 是否点赞
      like_count: number // 点赞数统计
      create_time: string // 创建时间
}

使用方法

<template>
  <CComment
    ref="ccRef"
    v-model:userInfo="userInfo"
    v-model:tableData="tableData"
    v-model:tableTotal="tableTotal"
    @likeFun="likeFun"
    @replyFun="replyFun"
    @deleteFun="deleteFun"
    :deleteMode="deleteMode"
  ></CComment>
  <view @tap="openComment">评论</view>
</template>

<script setup>
import CComment from "@/components/cc-comment";

// 发起新评论
let ccRef = ref(null);
function openComment() {
  ccRef.value.newCommentFun();
}

// 点赞回调事件
function likeFun({ params }, callback) {
  console.log("likeFun", params);
  // 当请求失败, 调用callback重置点赞效果;
  // Demo如下:
  // axios.post("http://xxx/like", { id: params }).then((res) => {
  //   if (res.code !== 0) {
  //     callback(res);
  //   }
  // });
}

// 回复回调事件
function replyFun({ params }, callback) {
  console.log("replyFun", params);
  // 当请求成功, 调用callback执行评论插入;
  // Demo如下:
  // axios.post("http://xxx/reply", { ...params }).then((res) => {
  //   if (res.code === 0) {
  //     callback(res);
  //   }
  // });
  const res = { id: Math.random() }; // 很重要的回参! 必须拿到后端返回评论id! 删除需要!
  setTimeout(() => callback(res), 500); // 目前为了展示效果, 直接执行callback
}

/** 删除回调事件
 * mode 删除模式
 * -- bind: 当被删除的一级评论存在回复评论, 那么该评论内容变更显示为[当前评论内容已被移除]
 * -- only: 仅删除当前评论(后端删除相关联的回复评论, 否则总数显示不对)
 * -- all : 删除所有评论包括回复评论
 */
const deleteMode = ref("all");
function deleteFun({ params, mode }, callback) {
  console.log("deleteFun", { params, mode });
  // 当请求成功, 调用callback执行评论删除;
  switch (deleteMode) {
    case "bind":
      // 逻辑: 调用接口进行评论内容修改 update
      setTimeout(() => callback(), 500); // 目前为了展示效果, 直接执行callback
      break;
    case "only":
      // 逻辑: 调用接口删除一个评论 delete
      setTimeout(() => callback(), 500); // 目前为了展示效果, 直接执行callback
      break;
    default:
      // all
      // 逻辑: 调用接口删除多个评论 [delete]
      // Demo如下:
      // axios.post("http://xxx/delete", { ids: params }).then((res) => {
      //   if (res.code === 0) {
      //     callback(res);
      //   }
      // });
      setTimeout(() => callback(), 500); // 目前为了展示效果, 直接执行callback
      break;
  }
}

// ----模拟数据------模拟数据------模拟数据----
// 当前登录用户信息
let userInfo = reactive({
  id: 120, // 评论id
  user_name: "ikun", // 用户名
  user_avatar:
    "https://pic1.zhimg.com/80/v2-a79071a705f55c5d88f6c74e6111fe84_720w.webp", // 用户头像
});
let tableTotal = ref(4);// 评论总数
let tableData = reactive([
  {
    id: 120, // 评论id
    parent_id: null, // 父级评论id
    reply_id: null, // 被回复人评论id
    reply_name: null, // 被回复人名称
    user_name: "ikun", // 用户名
    user_avatar:
      "https://pic1.zhimg.com/80/v2-a79071a705f55c5d88f6c74e6111fe84_720w.webp", // 评论者头像地址
    user_content: "唱,跳,rap,篮球", // 评论内容
    is_like: false, // 是否点赞
    like_count: 120, // 点赞数统计
    create_time: "2024-01-01 09:16", // 创建时间
  },
  {
    id: 130,
    parent_id: 120, // 评论的父级id
    reply_id: 120, // 被回复评论id
    reply_name: "ikun", // 被回复人名称
    user_name: "小黑子", // 用户名
    user_avatar:
      "https://pic2.zhimg.com/80/v2-06eade66ec837713d765b1557bf20b25_720w.webp", // 评论者头像地址
    user_content: "姬霓太美", // 评论内容
    is_like: false, // 是否点赞
    like_count: 67, // 点赞数统计
    create_time: "2024-01-01 17:06", // 创建时间
  },
  {
    id: 140,
    parent_id: 120, // 评论的父级id
    reply_id: 130, // 被回复评论id
    reply_name: "小黑子", // 被回复人名称
    user_name: "守护宗主维护宗门", // 用户名
    user_avatar:
      "https://pic3.zhimg.com/80/v2-244696a62fa750b8570cf56bfaa5b26a_720w.webp", // 评论者头像地址
    user_content: "你露出鸡脚了", // 评论内容
    is_like: false, // 是否点赞
    like_count: 16, // 点赞数统计
    create_time: "2024-01-02 23:08", // 创建时间
  },
  {
    id: 150,
    parent_id: null, // 评论的父级id
    reply_id: null, // 被回复评论id
    reply_name: null, // 被回复人名称
    user_name: "音乐制作人", // 用户名
    user_avatar:
      "https://pic2.zhimg.com/80/v2-88ec6f8c6d3305122664dd18a28730e5_720w.webp", // 评论者头像地址
    user_content:
      "只因你太美baby 只因你太美baby 只因你实在是太美baby 只因你太美baby 迎面走来的你让我如此蠢蠢欲动 这种感觉我从未有 Cause I got a crush on you who you 你是我的 我是你的 谁 再多一眼看一眼就会爆炸 再近一点靠近点快被融化", // 评论内容
    is_like: true, // 是否点赞
    like_count: 8, // 点赞数统计
    create_time: "2024-01-08 00:45", // 创建时间
  },
]);// 评论表

</script>

再放一遍下载地址

uni-app官方插件市场: cc-comment组件

感谢使用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

flask+mysql徐州市天气信息可视化分析系统-计算机毕业设计源码04600

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对天气信息等问题&#xff0c;对天气信息进行…

深度学习在交通标志识别中的应用

深度学习在交通标志识别中的应用 深度学习在交通标志识别中的应用1. 交通标志识别的背景2. CNN在交通标志识别中的应用3. 数据集准备4. 模型训练与优化5. 模型评估与部署结语 深度学习在交通标志识别中的应用 交通标志是道路上的重要元素&#xff0c;它们提供了关键的信息&…

网络的设置

一、网络设置 1.1查看linux基础的网络设置 网关 route -n ip地址ifconfigDNS服务器cat /etc/resolv.conf主机名hostname路由 route -n 网络连接状态ss 或者 netstat域名解析nslookup host 例题&#xff1a;除了ping&#xff0c;什么命令可以测试DNS服务器来解…

机器学习系列--R语言随机森林进行生存分析(2)

随机森林&#xff08;Breiman 2001a&#xff09;&#xff08;RF&#xff09;是一种非参数统计方法&#xff0c;需要没有关于响应的协变关系的分布假设。RF是一种强大的、非线性的技术&#xff0c;通过拟合一组树来稳定预测精度模型估计。随机生存森林&#xff08;RSF&#xff0…

【算法分析与设计】移动零

题目 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0…

【Github-Action】统计整个社区所有项目的贡献

thinkasany/organize-contributors 介绍&#x1f680;谁在用我效果&#x1f354; 使用指南示例仓库mdpagesyml配置yml demo 介绍 项目地址 如果你对github-action感兴趣&#xff0c;还可以看这篇文章&#xff0c; 这篇文章教会你如何开发Github Action&#xff0c;并且让你明…

2024年跨境电商上半年有哪些营销节日?

2024年伊始&#xff0c;跨境电商开启新一轮的营销竞技&#xff0c;那么首先需要客户需求&#xff0c;节假日与用户需求息息相关&#xff0c;那么接下来小编为大家整理2024上半年海外都有哪些节日和假期&#xff1f;跨境卖家如何见针对营销日历选品&#xff0c;助力卖家把握2024…

JavaScript中解锁Map和Set的力量

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ ✨ 前言 ES6带来了Map和Set两个新的数据结构 - 它们分别用于存放键值对和唯一值。Map和Set提供了更…

调试器加载错误,从任务栏打开可能会导致该问题 2024/1/8

&#x1f9e7;喜欢将常用软件固定在任务栏的用户肯定很苦恼这个问题 &#x1f9e7;问题复现 &#x1f9e7;这里先查找一下原因 &#x1f9e7;查看一下固定在任务栏的微信小程序开发工具的属性 如果不会打开任务栏图标属性界面的小伙伴请先翻到文章最后 &#x1f9e7;再使用同样…

数据结构与算法教程,数据结构C语言版教程!(第三部分、栈(Stack)和队列(Queue)详解)二

第三部分、栈(Stack)和队列(Queue)详解 栈和队列&#xff0c;严格意义上来说&#xff0c;也属于线性表&#xff0c;因为它们也都用于存储逻辑关系为 "一对一" 的数据&#xff0c;但由于它们比较特殊&#xff0c;因此将其单独作为一章&#xff0c;做重点讲解。 使用栈…

【JVM 基础】 Java 类加载机制

JVM 基础 - Java 类加载机制 类的生命周期类的加载: 查找并加载类的二进制数据连接验证: 确保被加载的类的正确性准备: 为类的静态变量分配内存&#xff0c;并将其初始化为默认值解析: 把类中的符号引用转换为直接引用 初始化使用卸载 类加载器&#xff0c; JVM类加载机制类加载…

「 CodeQL从入门到精通系列 」03.CodeQL常用术语介绍

相比其他代码检测工具&#xff0c;CodeQL中定义了很多专用术语&#xff0c;为了更快上手后续章节&#xff0c;本文对接下来要用到的术语做了统一汇总与解读。 1. 查询语言(QL) QL是一种声明性、面向对象的查询语言&#xff0c;经过优化&#xff0c;可实现对分层数据结构&#…

kafka入门(六):日志分段(LogSegment)

日志分段&#xff08;LogSegment&#xff09; Kafka的一个 主题可以分为多个分区。 一个分区可以有一至多个副本&#xff0c;每个副本对应一个日志文件。 每个日志文件对应一个至多个日志分段&#xff08;LogSegment&#xff09;。 每个日志分段还可以细分为索引文件、日志存储…

mybatis plus相同Id与xml配置错误时,mybatis plus解决逻辑

前言 处理做项目的问题&#xff0c;其中不乏奇奇怪怪的问题&#xff0c;其中mybatis plus的问题感觉有点隐蔽&#xff0c;有些是运行时出现&#xff0c;有些是运行到具体的逻辑触发&#xff0c;对于应用的状态监控提出了极大的挑战&#xff0c;应用的状态由健康检查接口提供&a…

facebook广告的基础知识与类型

Facebook广告是在Facebook平台上展示的一种数字广告形式&#xff0c;它允许广告主通过定位特定的受众群体来推广他们的产品、服务或品牌。以下是一些关于Facebook广告的基础知识&#xff1a; 支持Facebook广告的卡、556150、532959&#xff0c;点击获取 广告形式&#xff1a; …

【Proteus仿真】【Arduino单片机】智能感应温控风扇

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶显示模块、DS18B20温度、按键、声光报警、L293D电机驱动等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示传感器检…

.NET Framework 与 .NET Core 与 .NET Standard 之间的差异

介绍 在本文中&#xff0c;我们将探讨 .NET Framework、.NET Core 和 .NET Standard 之间的差异。 .NET Framework 与 .NET Core .NET框架.NET核心 历史 .NET Framework 是 .NET 的第一个实现。 .NET Core 是 .NET 的最新实现。 开源 .NET Framework 的某些组件是开源的。 .N…

前端实现搜索功能

最近遇到一个需求,用户在输入框输入关键字之后,点击搜索按钮后进行搜索,如下图,选中的数据在下面,上面展现的是搜索后的数据,现在选中了2条数据: 当用户输入KET后点击搜索,搜出的结果有16条,勾选全选选中后,将选中的16条的数据加到之前已选的2条数据里,于是此时已选…

认识Linux指令之 “ head tail ” 命令

01.head指令 head 与 tail 就像它的名字一样的浅显易懂&#xff0c;它是用来显示开头或结尾某个数量的文字区块&#xff0c;head 用来显示档案的开头至标准输出中&#xff0c;而 tail 想当然尔就是看档案的结尾。 语法&#xff1a; head [参数]... [文件]... 功能&#…

SAP CO11N报工批次分割(拆分)

CO11N做报工的时候&#xff0c;下阶料启用了批次&#xff0c;比如需要过账4166个&#xff0c;但是每一批次的库存都不满足4166个&#xff0c;所以需要拆分&#xff08;分割&#xff09;处理 这个时候我们就需要对这一行做分割处理 选中这一行&#xff0c;点击‘分割’按钮 弹…