本文将讲如何使用一个评论功能。本文的评论功能,是我自己写的一个网站的中的评论,所以大家可以先看看效果,地址:http://www.toheart.xin(已被注销)。好了废话不说直接开讲。
使用技术介绍:后端使用了springBoot+mybatis。前端使用了vue.js+element框架。数据库使用的是mysql。
关于后端:
一:首先数据库的设计
说明:commentId是该表的主键,fatherId是和commentId自关联的外键。子评论的fatherId就是父评论commentId。这样设计是为了方便递归查询。添加评论的功能就此省略,本文主要讲如何展示所有评论。
二、mybatis设计
1、mapper.java
List<CommentVO> getCommentList(@Param("articleId") int id,@Param("articleType") int articleType);
List<CommentVO> getCommentChild(int commentId);
说明: getCommentList方法是通过文章的id和文章的类型来查询所有评论,getCommentChild方法是查处该评论的所有子评论
2、mapper.xml
<resultMap id="commentVO" type="xin.toheart.door.controller.VO.CommentVO">
<id column="commentId" property="commentId"></id>
<collection property="child" column="commentId"
select="xin.toheart.door.mapper.CommonMapper.getCommentChild"
javaType="java.util.List"
ofType="xin.toheart.door.controller.VO.CommentVO"></collection>
</resultMap>
<select id="getCommentList" resultMap="commentVO">
select * from comment c ,user u where c.userId=u.userId and c.articleId=#{articleId} and c.articleType=#{articleType} and c.fatherId=0 order by c.commentTime desc
</select>
<resultMap id="child" type="xin.toheart.door.controller.VO.CommentVO">
<id column="commentId" property="commentId"></id>
<collection property="child" column="commentId"
select="xin.toheart.door.mapper.CommonMapper.getCommentChild"
javaType="java.util.List"
ofType="xin.toheart.door.controller.VO.CommentVO"></collection>
</resultMap>
<select id="getCommentChild" resultMap="child">
select * from comment c ,user u where c.userId=u.userId and fatherId=#{commentId} order by c.commentTime desc
</select>
说明:mapper.xml中使用了resultMap,目的是使用嵌套结果的方式实现一对多的查询(如若不了解请先了解resultMap的相关知识,提示很重要)。第一个resultMap的目的是查询出所有顶层评论及其顶层评论下的子评论,第二个resultMap的目的是递归查询(自循环)出所有的子评论。
三、vue设计(使用的是element框架)
我是将评论块设置成了一个组件,这个组件递归的将所有的评论都展示出来,详细代码如下:
<template>
<div style="margin-top: 20px;">
<el-col :span="24" style="padding-top: 5px" v-for="commentTopList in commentList" :key="commentTopList.commentId">
<el-col :span="3" style="text-align: left;padding-top: 10px"><img :src="commentTopList.imgUrl" v-if="commentTopList.fatherId === 0" style="width: 50px;height: 50px;border-radius: 50%"/><div v-if="commentTopList.fatherId !== 0" style="width: 50px;height: 50px;border-radius: 50%"></div></el-col>
<el-col :span="21" style="padding-top: 10px;padding-bottom: 20px">
<el-row style="font-size: 15px;">
<el-col :span="16" style="text-align: left;color: darkorange;"><span v-text="commentTopList.userName">话梦人生</span> <span v-if="fathername !== undefined" v-text="'回复 '+ fathername"></span></el-col>
<el-col :span="8" style="float: right;text-align: right;color: silver;font-family: 宋体" v-text="commentTopList.commentTime">2018年9月11日</el-col>
</el-row>
<el-row style="margin-top: 8px;">
<el-col :span="24">
<div @click="isShowComment(commentTopList.commentId);" style="width: 100%;text-align: left;text-indent: 2em;font-size: 15px;font-family: 宋体" v-text="commentTopList.commentContent">123</div>
<el-col style="margin-top: 10px;" v-show="isShow && curCommentId === commentTopList.commentId">
<div v-if="user.userId !== ''">
<el-input type="textarea" :rows="5" placeholder="觉得不错就说几句吧" v-model="discussContent"></el-input>
<el-button type="primary" style="margin-top: 10px;float: right" @click="replyComment(commentTopList.articleId,commentTopList.articleType,commentTopList.commentId);">发表评论</el-button>
</div>
<div v-else-if="user.userId === ''">
<el-button type="primary" style="margin-top: 10px;float: right" @click="login()">登录后评论</el-button>
</div>
</el-col>
</el-col>
</el-row>
<!--<el-row style="margin-top: 26px;">-->
<!--<el-col :span="23" style="text-align: right;">-->
<!--<div style="float: right;">-->
<!--<div class="icon-praise praise" style="height: 24px;margin-top: -2px;"></div><span v-text="1" style="margin-top: -10px;display: inline-block;"></span>-->
<!--</div>-->
<!--</el-col>-->
<!--</el-row>-->
<!--<el-row v-for="childs in commentTopList.child" :key="childs.commentId" style="text-align: left;margin-top: 20px;border-top: 1px dotted #ccc">-->
<!--<div style="color: silver;padding-top: 10px">-->
<!--<span v-text="childs.userName"></span><span> 回复 </span><span v-text="commentTopList.userName"></span>-->
<!--<span v-text="childs.commentTime" style="float: right"></span>-->
<!--</div>-->
<!--<p v-text="childs.commentContent"></p>-->
<!--</el-row>-->
</el-col>
<comment v-if="commentTopList.child !== null" :commentList="commentTopList.child" :fathername="commentTopList.userName"></comment>
</el-col>
</div>
</template>
<script>
import comment from './index.vue'
import { increaseComment, getComment } from '@/api/common'
import { mapState } from 'vuex'
export default {
computed: mapState([
'user'
]),
data () {
return {
discussContent: '',
isShow: false,
curCommentId: 0
}
},
name: 'comment',
props: ['commentList', 'fathername'],
components: {
comment
},
methods: {
login () {
window.location.href = 'http://www.toheart.xin:5201/login'
},
getCommentList (id, type) {
getComment(id, type).then(response => {
if (response.state) {
this.$emit('commentListChange', response.data.commentList)
}
})
},
replyComment (id, type, fatherId) {
increaseComment(id, type, fatherId, this.discussContent).then(response => {
this.getCommentList(id, type)
this.isShow = false
this.discussContent = ''
console.log('-------')
})
},
isShowComment (id) {
console.log(id)
this.curCommentId = id
if (this.isShow) {
this.isShow = false
} else {
this.isShow = true
}
}
}
}
</script>
使用这个组件使用的方式如下:
<comment :commentList = "commentList" @commentListChange="changeCommentList"></comment>
changeCommentList (data) {
this.commentList = data
},
展示效果:详情展示请看:http://www.toheart.xin(已被注销)
说明:这个评论做的比较简单,最重要的是要理清思路,多去参考其他网站的评论功能,这样自己也会做出这个功能的。
这个项目由于工作原因(懒惰的借口)没有继续下去,加上当时能力有限,所以这个评论的功能可能也有很多bug,这个简单demo仅供借鉴。 附上GitHub地址,希望对你有所帮助。只要有心,一切皆有可能!
http://www.toheart.xin ---》这个网站已被注销。
github地址:Java: https://github.com/xsh520/toheartVueH.git