先看需求
::: hljs-center
:::
我们需要将评论数据进行渲染成如图所示,后端给我们返回的数据格式又是啥样的呢?答案就是一级一级的父子层级嵌套的数据结构:
::: hljs-center
:::
面对这样的数据结构,我们怎么渲染呢?
通过递归的形式渲染就比较可行
首先,我们创建一个回复评论的组件,父组件中将评论的回复数组传给子组件,在子组件中进行渲染,如果回复的数组中还有子回复那么这时候把数据传给回复组件即可。这样就能达到递归渲染数组的目的了。
引用回复组件
在父组件中引用回复组件
import replyComment from '../comment-item/comment-item.vue'components: { replyComment},<!-- 回复 --> <replyComment style="padding-left: 68rpx;" :commentChildren="item.children" @child_up="handleCommentUp" @child_down="handleCommentDown" @child_reply="handleCommentInputPopupShow"></replyComment>
回复组件
replyComment:
<template> <view class="reply-content-wrapper"> <view class="comment-reply-data" v-for="(item,index) in commentChildren" :key="index"> <view class="comment-reply-user"> <view class="comment-root-header flex-row"> <image :src="item.criticImg" mode=""></image> <view class="username"> {{item.criticName}} </view> </view> <view class="replycomment-content"> <text>回复</text><text class="replyer">{{item.reCriticName}}</text> <text>{{item.comment}}</text> </view> <view class="comment-data flex-row-space"> <view class="create-time"> {{formatDate(item.createTime)}} </view> <view class="operation-icon flex-row"> <view class="operation-item"> <i class="icon iconzan_before" @tap="handleCommentUp(item.id)"></i> <text>{{item.supportCount}}</text> </view> <view class="operation-item"> <i class="icon iconcai_before" @tap="handleCommentDown(item.id)"></i> <text>{{item.opposeCount}}</text> </view> <view class="operation-item"> <i class="icon iconpinglun" @tap="handleCommentInputPopupShow(item)"></i> </view> </view> </view> </view> <replyComment v-if="item.children" :commentChildren="item.children" @child_up="handleCommentUp" @child_down="handleCommentDown" @child_reply="handleCommentInputPopupShow"></replyComment> </view> </view></template><script> import { formateTime } from '../../utils/index.js' export default { name: 'replyComment', props: { commentChildren: { type: Array, default: [] } }, data() { return { }; }, methods: { // 格式化时间 formatDate(time) { if (!time) { return '' } return formateTime(time) }, handleCommentUp(id) { this.$emit('child_up', id) }, handleCommentDown(id) { this.$emit('child_down', id) }, handleCommentInputPopupShow(item) { this.$emit('child_reply', item) }, } }</script><style lang="less" scoped> .comment-reply-data { .comment-root-header { color: #333333; margin: 27rpx 0; image { width: 48rpx; height: 48rpx; border-radius: 40rpx; margin-right: 20rpx; } } .comment-root-user { border-bottom: 2rpx solid #eee; } image { width: 48rpx; height: 48rpx; border-radius: 40rpx; margin-right: 20rpx; } .replycomment-content { margin-bottom: 20rpx; word-break: break-all; .replyer { display: inline-block; padding: 0 12rpx; color: #333333; position: relative; bottom: 2rpx; } } .comment-data { color: #666; line-height: 20rpx; font-size: 20rpx; padding-bottom: 28rpx; border-bottom: 2rpx solid #EDEDED; .operation-icon { .operation-item { margin-left: 49rpx; .icon { font-size: 22rpx; } } } // 点赞 .active-support { animation-name: support; animation-duration: 500ms; animation-iteration-count: 1; animation-fill-mode: forwards; } } }</style>
那么实际效果呢?
::: hljs-center
:::
其实,刚开始看到这个数据结构十分头疼,后来仔细想想递归是能够解决的,然后就开始动手,没想到真就实现了。开发中我们可能会遇到各种需求,只要冷静下来好好想想,总能找到解决办法的。
老铁们可以关注我的个人公众号
也可以去我的博客瞅瞅