最近需要写一个评论模块,然后就来csdn看了一下,结构差不多的,然后写完了,就想摸鱼一下子,介绍一下这个评论。
其实前端东西挺少的,核心就在一个组件递归使用(要注意判断递归结束的条件)。vue3模板代码。
<template>
<div>
<div class="comment-list">
<div class="comment-item">
<div :style="{ 'margin-left': (comment.lvl - 1) * 48 + 'px' }" class="user-box">
<a-avatar class="avatar" :src="comment.avatarUrl" />
<span>{{ comment.name }}</span>
</div>
<div :style="{ 'margin-left': comment.lvl * 48 + 'px' }" class="content">
{{ comment.text }}
</div>
<div :style="{ 'margin-left': comment.lvl * 48 + 'px' }" class="footer-box">
<span>{{ comment.time }}</span>
<div class="reply">
<div class="mr-6">
<SvgIcon class="mr-1" name="reply" size="16" />
<span>回复</span>
</div>
<div>
<SvgIcon class="mr-1" name="like" size="16" />
<span>{{ comment.like }}</span>
</div>
</div>
</div>
</div>
<div v-if="comment.replies?.length">
<CommentItem v-for="reply in comment.replies" :key="reply.id" :comment="reply" />
</div>
</div>
</div>
</template>
js部分,现在就值写了前端,因为项目里面配置了一些全局compositionApi,所以模板写法不一样的,需要自己修改。
<script name="CommentItem" lang="ts" setup>
import { SvgIcon } from '@/components/Icon';
const props = defineProps({
comment: {
type: Object,
default: () => ([]),
},
});
</script>
css部分
<style lang="less" scoped>
.comment-list {
display: flex;
flex-direction: column;
.comment-item {
margin: 10px 0;
.user-box {
display: flex;
flex-direction: row;
align-items: center;
color: rgb(0 0 0 / 100%);
font-size: 20px;
font-weight: 550;
}
.content {
padding-bottom: 10px;
color: rgb(0 0 0 / 85%);
font-family: 'PingFang SC';
font-size: 16px;
font-weight: 400;
line-height: 160%;
}
.footer-box {
display: flex;
justify-content: space-between;
color: rgb(0 0 0 / 55%);
font-size: 16px;
font-weight: 400;
.reply {
display: flex;
flex-direction: flex-start;
cursor: pointer;
}
}
}
}
</style>
然后在外部引用一下组件就好了。
<CommentItem v-for="comment in comments" :key="comment.id" :comment="comment" />
当然,评论还是js部分难写一点吧,因为现在不是前后端分离开发么,所以就前端先行喽,后端还差很多。js部分后续写了补上吧。因为评论应该会分页,点赞数据如何和用户关联(当然点赞表、评论表、回复表这些不是前端需要考虑的。)
(小插曲,我之前在csdn上测试评论,删除、新增、然后操作频繁,触发了评论隐藏机制。。。)