我在做项目时遇到了需要评论回复功能。由于iview UI没有该组件,所以自定义设计

我的博客地址:博客地址,点击访问可以查看评论区。
  • 效果图如下
    在这里插入图片描述
    支持评论和多级回复
废话不多说,vue代码如下:
  • 评论组件
<template>
    <div>

        <List item-layout="vertical" size="small" :split="false">

            <ListItem v-for="item in commentList" :key="item.id">
                <ListItem>
                    <Avatar shape="square" size="small" :src="item.avatar"></Avatar>&nbsp;<span
                        style="color: #2d9aff">{{item.nickname}}</span>
                    <li style="margin-left: 2.5%">{{item.content}}</li>
                    <template slot="action">
                        <li>
                            <Icon type="ios-calendar-outline"/>
                            {{dateFilter(item.createTime)}}
                        </li>
                        <li>
                            <span @click="showCommentInput(item,item)"><Icon type="ios-chatbubbles-outline"/> 回复</span>

                        </li>
                    </template>
                </ListItem>

                <div v-if="item.replyComments" class="reply">
                    <Reply :replyComment="item.replyComments" :comment='item'
                           v-on:showCommentInput="showCommentInput"></Reply>
                </div>
                <Divider/>
            </ListItem>
        </List>

        <div id="target">
            <Input
                    v-model="inputComment"
                    type="textarea"
                    :rows="3"
                    :placeholder="placeholders">
            </Input>
            <div style="text-align: right;margin-top: 10px">
                <Button @click="cancel" style="margin-right: 10px">取消</Button>
                <Button type="primary" round @click="commitComment">确定</Button>
            </div>
        </div>
    </div>
</template>

<script>

    import Reply from './Reply'

    export default {
        components: {
            Reply,
        },
        name: 'Comment',
        props: {
            commentList: Array,
            blogId: null,
        },
        data() {
            return {
                //评论内容
                inputComment: '',
                //输入框默认内容
                placeholders: '写下你的评论',

            }
        },

        methods: {
            /**
             * 点击取消按钮
             */
            cancel() {
                this.inputComment = '';
                this.placeholders = '写下你的评论';
                this.fromId = '';
            },
            /**
             * 提交评论
             */
            async commitComment() {
                const redata = JSON.parse(window.sessionStorage.getItem("user"));
                if (!redata) {
                    this.$Message.warning({
                        background: true,
                        content: '发表评论请先登录!',

                    });
                    scrollTo(0, 0);
                } else {
                    if (!this.inputComment) {
                        this.$Message.warning({
                            background: true,
                            content: '评论信息不能为空!',

                        });
                    } else {
                        const comment = {
                            nickname: redata.nickname,
                            content: this.inputComment,
                            avatar: redata.headimgurl,
                            blog: {id: this.blogId,},
                            pid: this.fromId
                        };
                        const {data: result} = await this.$http.post("saveComment", comment);
                        if (result.code === 200) {
                            //调用父类blog中的根据blogid获取评论信息的方法
                            this.$Message.success(result.message)
                            this.$emit("on-comment", this.blogId);
                        }
                    }
                }

                this.inputComment = '';
            },
            //根据id查询该博客的评论信息
            async showCommentById(id) {
                const {data: result} = await this.$http.get("getListByBlogId/" + id)
                if (result.code === 200) {
                    this.commentList = result.data
                } else {
                    this.$Message.success(result.message)
                }
            },
            /**
             * 点击评论按钮显示输入框
             * item: 当前大评论
             * reply: 当前回复的评论
             */

            showCommentInput(item, reply) {
                if (reply) {
                    this.placeholders = "@" + reply.nickname + " "
                } else {
                    this.inputComment = ''
                }
                //当点击了回复时,页面滚动到评论框的位置
                document.getElementById("target").scrollIntoView();
                this.fromId = reply.id
            },
            //格式化时间的方法
            dateFilter: function (input) {
                var d = new Date(input);
                var year = d.getFullYear();
                var month = d.getMonth() < 9 ? "0" + (d.getMonth() + 1) : "" + (d.getMonth() + 1);
                var day = d.getDate() < 10 ? "0" + d.getDate() : "" + d.getDate();
                var hour = d.getHours() < 10 ? "0" + d.getHours() : "" + d.getHours();
                var minutes = d.getMinutes() < 10 ? "0" + d.getMinutes() : "" + d.getMinutes();
                var seconds = d.getSeconds() < 10 ? "0" + d.getSeconds() : "" + d.getSeconds();
                return (year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds);
            },
        },
    }

</script>

<style scoped lang="less">
    .reply {
        margin-left: 15px;
    }

</style>




  • 回复组件
<template>
    <div>
        <List item-layout="vertical" :split="false" size="small">
            <ListItem v-for="item in replyComment" :key="item.id" class="reply">
                <ListItem>
                    <Avatar shape="square" size="small" :src="item.avatar"></Avatar>&nbsp;<span
                        style="color: #2d9aff">{{item.nickname}}&nbsp;</span>回复:
                    &nbsp;<span style="color: #2d9aff">{{comment.nickname}}</span>
                    <li style="margin-left: 2.5%">{{item.content}}</li>

                    <template slot="action">
                        <li>
                            <Icon type="ios-calendar-outline"/>
                            {{dateFilter(item.createTime)}}
                        </li>
                        <li>
                            <span @click="toParent(comment,item)">
                                <Icon type="ios-chatbubbles-outline"/> 回复
                            </span>
                        </li>
                    </template>
                </ListItem>
                <div v-if="item.replyComments" class="reply">
                    <reply :replyComment="item.replyComments" :comment='item'
                           v-bind="$attrs" v-on="$listeners"></reply>
                </div>

            </ListItem>
        </List>
    </div>

</template>
<script>

    export default {
        name: 'reply',
        props: {
            comment: {},
            replyComment: Array,

        },
        data() {
            return {}
        },
        methods: {
            toParent(comment, item) {
                this.$emit('showCommentInput',comment, item);
            },
            //格式化时间的方法
            dateFilter: function (input) {
                var d = new Date(input);
                var year = d.getFullYear();
                var month = d.getMonth() < 9 ? "0" + (d.getMonth() + 1) : "" + (d.getMonth() + 1);
                var day = d.getDate() < 10 ? "0" + d.getDate() : "" + d.getDate();
                var hour = d.getHours() < 10 ? "0" + d.getHours() : "" + d.getHours();
                var minutes = d.getMinutes() < 10 ? "0" + d.getMinutes() : "" + d.getMinutes();
                var seconds = d.getSeconds() < 10 ? "0" + d.getSeconds() : "" + d.getSeconds();
                return (year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds);
            },
        }
    }
</script>

<style scoped>
    .reply {
        margin-left: 10px;
    }

</style>

  • 如果需要使用评论组件只需要在指定位置引入即可,代码如下:
  • 在当前vue中要先引入该评论组件。才能使用!!
<Comment :commentList="commentList" :blogId="blogId" @on-comment="showCommentById"></Comment>
  • showCommentById
            //根据id查询该博客的评论信息
            async showCommentById(id) {
                const {data: result} = await this.$http.get("getListByBlogId/" + id)
                if (result.code === 200) {
                    this.commentList = result.data
                } else {
                    this.$Message.success(result.message)
                }
            },
下面介绍评论的数据结构如下:
[{
		"id": 1,
		"pid": 0,
		"nickname": "张三",
		"content": "你们好",
		"avatar": "http://thirdwx.qlogo.cn/mmopen/0Xxpbic36D0ELicBiaCEgiaUSRVqTINadg8n7ePWZ0NgWaoh4ZA9qWicYly2eKXtDAW3nLicicmdheRiayLN4v3b44zia/132",
		"createTime": "2020-04-12T06:32:20.613+0000",
		"replyComments": [{
			"id": 2,
			"pid": 1,
			"nickname": "李四",
			"content": "你好",
			"avatar": "http://thirdwx.qlogo.cn/mmopen/0Xxpbic36DhJ5tCEgiaUSRVqTINadg8n7ePWZ0NgWaoh4ZA9qWicYly2eKXtDAW3nLicicmdheRiayLN4v3b44zia/132",
			"createTime": "2020-04-12T06:32:31.699+0000",
			"replyComments": []
		}]
	},
	{
		"id": 3,
		"pid": 0,
		"nickname": "王五",
		"content": "猪吗?",
		"avatar": "http://thirdwx.qlogo.cn/mmopen/0Xxpbic36DhJ5tLwiaJAAJV0ELicBiaCEgiaWaoh4ZA9qWicYly2eKXtDAW3nLicicmdheRiayLN4v3b44zia/132",
		"createTime": "2020-04-12T06:34:37.146+0000",
		"replyComments": [{
			"id": 4,
			"pid": 3,
			"nickname": "赵六",
			"content": "??",
			"avatar": "http://thirdwx.qlogo.cn/mmopen/0Xxpbic36DhJ5tLwiaJAqTINadg8n7ePWZ0NgWaoh4ZA9qWicYly2eKXtDAW3nLicicmdheRiayLN4v3b44zia/132",
			"createTime": "2020-04-12T07:03:47.873+0000",
			"replyComments": []
		}]
	},
]
Logo

前往低代码交流专区

更多推荐