留言界面主要由两个组件所构成——留言区组件以及评论表单的组件
3.1主视图Messeage.vue <template> <div> <comment-message @handleReply="handleReply" :commentList="comments"></comment-message> <comment-area @reload="reload" :parentMsgId="replyMsgId" :replyMsgUsername="replyMsgUsername"></comment-area> </div> </template> <script> import CommentMessage from "components/common/comment/CommentMessage"; import CommentArea from "components/common/comment/CommentArea"; import { findAllMsg } from "network/ajax"; export default { name: "Message", components: { CommentMessage, CommentArea }, data() { return { comments: [], replyMsgId: "", replyMsgUsername: "" }; }, mounted() { findAllMsg() .then(res => { this.comments = res.data.messages; }) .catch(err => { console.log(err); this.$router.push("/500"); }); }, methods: { handleReply(data) { this.replyMsgId = data.msgId; this.replyMsgUsername = data.msgUsername; }, reload() { this.$emit("reload") } } }; </script> <style> </style> 3.2 留言区域组件CommentMessage.vue: <template> <div> <div v-if="isEmpty(commentList)">暂无留言内容</div> <div v-else>留言内容</div> <comment @handleReply="handleReply" v-for="(item1, index) in commentList" :key="'parent-' + index" :comment="item1" > <!-- 二层留言 --> <template #childComment v-if="!isEmpty(item1.children)"> <comment v-for="(item2, index) in item1.children" :key="'children-' + index" :comment="item2" @handleReply="handleReply" ></comment> </template> </comment> </div> </template> <script> import Comment from "./Comment"; import Vue from "vue"; export default { name: "CommentMessage", components: { Comment }, props: { commentList: { type: Array, default: [] } }, methods: { isEmpty(ls) { return ls.length === 0; }, handleReply(data) { this.$emit("handleReply", { msgId: data.msgId, msgUsername: data.msgUsername }); } } }; </script> <style scoped> .head-message { font-size: 20px; text-align: center; } </style> 3.3 留言区域由多个Comment留言组件所构成,留言组件定义如下 <template> <a-comment> <span slot="actions" key="comment-basic-reply-to" @click="handlReply(comment.id, comment.username)" > <a href="#my-textarea">回复</a> </span> <a slot="author">{{comment.username}}</a> <a v-if="comment.parent_msg_username" slot="author" >@{{comment.parent_msg_username}}</a> <a-avatar slot="avatar" :src="require('assets/images/login_logo.png')" alt /> <p slot="content">{{comment.content}}</p> <a-tooltip slot="datetime"> <span>{{comment.date}}</span> </a-tooltip> <slot></slot> </a-comment> </template> <script> export default { name: "Comment", props: { comment: "" }, methods: { handlReply(msgId, msgUsername) { this.$emit("handleReply", { msgId, msgUsername }); } } }; </script> <style scoped> .reply-to { padding-left: 5px; color: #409eff; font-weight: 500; font-size: 15px; } </style> 3.4 添加留言或回复的表单组件CommentArea.vue <template> <div> <a-comment> <a-avatar slot="avatar" :src="require('assets/images/login_logo.png')" alt="Han Solo" /> <div slot="content"> <a-form-item> <a-textarea :rows="4" v-model="content" /> </a-form-item> <a-form-item> <a-button html-type="submit" :loading="submitting" type="primary" @click="handleSubmit" >添加留言</a-button> </a-form-item> </div> </a-comment> </div> </template> <script> import {insertMsg} from 'network/ajax.js' export default { data() { return { content: "", submitting: false }; }, props: { parentMsgId: "", replyMsgUsername: "" }, watch: { replyMsgUsername() { document .querySelector("#my-textarea") .setAttribute("placeholder", "回复: " + "@" + this.replyMsgUsername); } }, methods: { handleSubmit() { if (!this.content) { return; } this.submitting = true; insertMsg(this.content, this.parentMsgId, this.$store.state.userId).then(res => { this.submitting = false; this.content = ""; document .querySelector("#my-textarea") .setAttribute("placeholder", ''); this.$emit('reload') }).catch(err => { console.log(err); this.$router.push('/500') }) }, handleChange(e) { this.value = e.target.value; } } }; </script>组装完成后实现的功能有:
留言界面的展示
点击回复按钮跳到留言表单(这里我直接用了a标签来锚定位,试过用scrollToView来平滑滚动过去,但不知道为什么只有第一次点击回复按钮时才能平滑滚动到,之后再点击他就不滚动了。。。),并把被回复者的用户名显示在placeholder中