当前位置: 首页 > ops >正文

Vue 评论组件设计 V1.0

简介

基于 Element Plus 封装的一套二级评论组件。

算是 Comment V1.0 版本吧,总体还是有很多不完善的地方,后续在安排改进。先用着先吧,哈哈。

本文不算是教学,只是记录设计该组件的思路,虽然只是简单的记录了一下过程,给自己看的,各位仅供参考。

组件演示

Basic / 一级评论

image-20250902200408552

二级评论

点击回复按钮

image-20250902200737222

二级评论默认不展示,只显示回复条目

image-20250902200502997

查看二级评论列表

image-20250902200853665

二级评论回复

image-20250902201125830

查看评论数量

image-20250902201319542

展开评论回复列表

image-20250902201415788

组件分类

CommentEdit

CommentEdit 组件:编辑和发布评论。

image-20250902202353678

对于该组件就不多说什么了,直接用 Element Plus 组件库的表单组件套上直接用就行。

Comment

Comment 组件:作为评论内容的载体,渲染评论。

image-20250902201319542

组件的使用方式

<script setup>
import { ref, onMounted, watch, defineAsyncComponent } from 'vue'
...
import { getRootArticleCommentList } from '@/api/comment'
const commentData = ref()
...
const refreshComment = () => {getRootArticleCommentList(articleId).then((resp) => {if(resp.code === 1)commentData.value = resp.data})
}
...
</script><template><div class="content">...<!-- 评论列表 --><div class="comment-list"><!-- 一级评论,将评论信息 item 通过 data 传递给组件内部,以便渲染和获取二级评论 --><comment :data="item" v-for="item in commentData" :refresh-comment="refreshComment"><!-- 内嵌二级评论,二级评论的数据由一级评论 comment 内部控制 --><template #review-list="{ reviewList }"><comment :review="true" :data="child" v-for="child in reviewList" :refresh-comment="refreshComment"></comment></template></comment></div></div>
</template>
...

commentData 似乎通过 getRootArticleCommentList API 得到的相应数据,它仅请求一级评论,不请求二级评论。格式如下:

"data": [{"id": 103,"nickname": "哈哈哈","website": "web","avatarHash": "1643ec4b1d1ccee82772f1c7043a27db","createTime": 1756814289000,"beforeTime": "星期二","content": "<span>你好啊!</span><br>",..."reviewTotal": 2}
]

Comment

HTML

<template><div class="comment"><div class="main"><!-- 头像 --><div><img :src="`https://cravatar.com/avatar/${ data.avatarHash }`" alt=""></div><!-- 内容主体 --><div class="box"><!-- 当前评论是二级评论 --><p v-if="review"><span class="name" v-if="data.website == null">{{ data.nickname }}</span><a :href="'https://' + data.website" target="_blank" class="name" v-else>{{ data.nickname }}</a><strong>回复</strong><span class="name">{{ data.toNickname }}</span>·<span class="time">{{ data.beforeTime }}</span><el-tag type="success" size="small" v-if="data.isTitle">{{ data.title }}</el-tag></p><!-- 当前评论不是二级评论,是一级评论 --><p v-else><span class="name" v-if="data.website == null">{{ data.nickname }}</span><a :href="'https://' + data.website" target="_blank" class="name" v-else>{{ data.nickname }}</a>·<span class="time">{{ data.beforeTime }}</span><el-tag type="success" size="small" v-if="data.isTitle">{{ data.title }}</el-tag></p><!-- 评论内容 --><div class="content" v-html="data.content"></div><!-- [回复] 按钮 --><span class="review" @click="enabledReview">回复</span><!-- 如果当前评论不是二级评论,且一级评论下有回复(即存在二级评论) --><span class="review" v-if="!review && data.reviewTotal > 0" @click="setReviewListVisabled">展开 {{ data.reviewTotal }} 条回复</span><!-- 评论发布与回复 --><comment-editv-if="commentEditVisabled".../></div></div><!-- 二级评论列表 --><div class="review-list" v-if="reviewListVisabled" v-loading="loadingFlag"><slot name="review-list" :review-list="reviewList"></slot><div class="close-review-list" @click="reviewListVisabled = false">关闭回复列表</div></div></div>
</template>

先来看看 comment 组件在外部使用时的模样:

...<!-- 一级评论,将评论信息 item 通过 data 传递给组件内部,以便渲染和获取二级评论 --><comment :data="item" v-for="item in commentData" :refresh-comment="refreshComment"><!-- 内嵌二级评论,二级评论的数据由一级评论 comment 内部控制 --><template #review-list="{ reviewList }"><comment :review="true" :data="child" v-for="child in reviewList" :refresh-comment="refreshComment"></comment></template></comment>
...

在 comment 子组件内部通过 prop.data 得到的数据其中的 commentId 去查询得到当前评论下的二级评论列表 reviewList。然后通过 <slot> 插槽将 reviewList 传递给父组件,父组件再来进行渲染。

js

import { ref } from 'vue'
import CommentEdit from '../CommentEdit/CommentEdit.vue'import { getReviewArticleCommentList, ... } from '@/api/comment'const props = defineProps({review: { Type: Boolean }, 			// true 代表当前评论是二级评论,false 代表当前评论是一级评论data: { Type: Object }, 				// 评论具体信息,包括头像、评论时间、昵称、评论内容等信息refreshComment: { Type: Function } 	// 通过这个函数可以刷新评论
})const commentEditVisabled = ref(false)  // true 时将显示 comment-edit 组件
const enabledReview = () => {commentEditVisabled.value = !commentEditVisabled.value
}const reviewList = ref() // 当前评论下的二级评论列表
const loadingFlag = ref(true)
const reviewListVisabled = ref(false) // 是否显示二级评论列表const setReviewListVisabled = () => {loadingFlag.value = truereviewListVisabled.value = trueif(props.data.articleId) {// 获取当前评论回复列表getReviewArticleCommentList(props.data.articleId, props.data.id).then((resp) => {if(resp.code === 1)reviewList.value = resp.dataloadingFlag.value = false})} else {...}
}// 刷新评论的回调
const refreshCommentCallback = () => {props.refreshComment()
}

或许可以看看我的博文:https://fanjuanddz.com/article/37

http://www.xdnf.cn/news/19695.html

相关文章:

  • JVM 的 C1/C2 编译器
  • AI在金融、医疗、教育、制造业等领域的落地案例(含代码、流程图、Prompt示例与图表)
  • Archlinux KDE 下 Fcitx5 输入法的配置与美化
  • 第二十章 ESP32S3 IIC_EEPROM 实验
  • 【计算机网络】TCP状态转移
  • 开发板直连电脑的搭建网络环境(以正点原子阿尔法imx6ull开发板为讲解)
  • Flutter代码生成:告别重复劳动,效率飙升
  • 《我是如何用C语言写工控系统的漏洞和Bug》连载(1)内容大纲
  • FART 自动化脱壳框架优化实战:Bug 修复与代码改进记录
  • 充电枪结构设计-经验总结
  • 计算机网络:概述层---TCP/IP参考模型
  • shell编程从0基础--进阶 1
  • Day20_【机器学习—逻辑回归 (1)—原理】
  • 电子病历空缺句的语言学特征描述与自动分类探析(以GPT-5为例)(上)
  • 找Jenkins代替工具,可以体验下这款国产开源CICD工具
  • Web 集群高可用全方案:Keepalived+LVS (DR) 负载均衡 + Apache 服务 + NFS 共享存储搭建指南
  • 【C++】深入浅出:string类模拟实现全解析
  • 碰一下可打开小程序,在web系统中如何嵌入将小程序写入NFC
  • 企业文档安全守护者全面测评:7款加密软件深度解析,让商业机密固若金汤
  • Parasoft C/C++test案例:基于CERT/CWE的代码合规自动化
  • 力扣hot100:螺旋矩阵(边界压缩,方向模拟)(54)
  • Canaan 阿瓦隆 A1246I 81T矿机评测:性能、功耗与能效全面分析
  • 高效对象属性复制工具
  • 2025 年行政岗转型突破:解锁技能提升新方向
  • 【V8引擎】介绍
  • 基因表达数据的K-M生存曲线的数据处理及绘制
  • C++条件变量学习
  • UML状态图之trigger(触发器)、guard(守卫条件)和action(动作)
  • Linux 文本处理神器——sed
  • 拔河(蓝桥杯)(前缀和)