Vue.js实现文章评论和回复评论功能
发布时间 - 2026-01-11 00:50:29 点击率:次本来想把这个页面用jade渲染出来、评论部分用vue,但是想了想觉得麻烦,最后还是整个用vue的组件搞定他吧。
先上在线demo:http://jsbin.com/ceqifo/1/edit?js,output

再上效果图
可直接评论,点击别人的评论能回复别人的评论。
html
<div id="comment"> <article-content v-bind:article="article"></article-content> <commemt-content v-bind:comment="comment" v-on:change="changCommmer"></commemt-content> <comment-textarea v-bind:type="type" v-bind:name="oldComment" v-on:submit="addComment" v-on:canel="canelCommit"></comment-textarea> </div>
数据全都由根组件绑定下去的。这里还监听了几个事件。
<article-content是文章内容的组件,没啥好讲的,直接把数据绑定进去子组件就行了。这里我是直接绑定一个obj而不是把标题、时间等等详细的信息分别绑定进去。因为直接绑定一个对象,子组件可以用.的方式很好的调用,比分开写好多了。
<article-content组件–文本
然后先说个简单点的,<comment-textarea>,文本框的那个组件。
Vue.component('commentTextarea',{
template:'\
<div class="commentBox">\
<h3>发表评论</h3>\
<b v-if="type">你回复 {{name}}</b>\
<textarea name="" value="请填写评论内容" v-model="commentText"></textarea>\
<button class="btn" @click="addComment">发表</button>\
<button class="btn" @click="canelComment">取消</button>\
</div>',
props: ['type','name'],
data: function(){
return {commentText:""}
},
methods: {
addComment: function() {
this.$emit("submit",this.commentText);
this.commentText = "";
},
canelComment: function() {
this.$emit("canel");
this.commentText = "";
}
}
});
type是如果点击了别人的评论,会显示 ”你回复xxx “ 的提示框,这个因为跨了组件通信而且两组件不是父子组件但是是兄弟组件,我把他们的通信挂在了父组件的一个属性上,实现通信。
文本框内的内容用一个v-model双向绑定,如果点击了确定,就触发一个 addComment事件并把文本内容传给父组件,父组件会监听事件。
commemt-content组件–评论内容
先来确定json格式
comment: [
{
name: "有毒的黄同学", //评论人名字
time: "2016-08-17",
content: "好,讲得非常好,good",
reply: [ //回复评论的信息,是一个数组,如果没内容就是一个空数组
{
responder: "傲娇的", //评论者
reviewers: "有毒的黄同学", //被评论者
time: "2016-09-05",
content: "你说得对"
}
}
]
再来看commemt-content组件
Vue.component('commemt-content',{
template:'\
<div class="commentBox">\
<h3>评论</h3>\
<p v-if="comment.length==0">暂无评论,我来发表第一篇评论!</p>\
<div v-else>\
<div class="comment" v-for="(item,index) in comment" v-bind:index="index" >\
<b>{{item.name}}<span>{{item.time}}</span></b>\
<p @click="changeCommenter(item.name,index)">{{item.content}}</p>\
<div v-if="item.reply.length > 0">\
<div class="reply" v-for="reply in item.reply">\
<b>{{reply.responder}} 回复 {{reply.reviewers}}<span>{{reply.time}}</span></b>\
<p @click="changeCommenter(reply.responder,index)"">{{reply.content}}</p>\
</div>\
</div>\
</div>\
</div>\
</div>',
props: ['comment'],
methods: {
changeCommenter: function(name,index) {
this.$emit("change",name,index);
}
}
});
如果没有内容,则显示 “暂无评论,我来发表第一篇评论!”。如果有内容就开始遍历。因为点击评论要知道第几条,所以每条评论要绑一个v-bind:index="index"
到了二次评论那块,还是遍历reply数组,绑定该绑定的。因为就算点击内容,也是加到那条一级评论的最下面,所以两个点击事件我都是绑定了同一个事件。只是传进去的名字不一样而已,后面那个index都是一级评论的index。
changeCommenter事件触发了change,父组件监听,执行相应行为。
父组件
var comment = new Vue({
el: "#comment",
data: {
commenter: "session", //评论人,这里会从session拿
type: 0, //0为评论作者1为评论别人的评论
oldComment: null, //久评论者的名字
chosedIndex: -1, //被选中的评论的index
article: {
title: "当归泡水喝的九大功效",
time: "2016-07-12",
read:50,
content: ""
},
comment: [] //评论内容
},
methods: {
//添加评论
addComment: function(data) {
if(this.type == 0) {
this.comment.push({
name: 'session',
time: getTime(),
content: data,
reply: []
});
//服务器端
}else if(this.type == 1){
this.comment[this.chosedIndex].reply.push({
responder: 'session',
reviewers:this.comment[this.chosedIndex].name,
time: getTime(),
content: data
});
this.type = 0;
}
},
//监听到了点击了别人的评论
changCommmer: function(name,index) {
this.oldComment = name;
this.chosedIndex = index;
this.type = 1;
},
//监听到了取消评论
canelCommit: function() {
this.type = 0;
}
}
})
data那里。。。实在是取名困难症啊。。。commenter是当前登录名,这里到时候会session里拿;type就是看到底是评论作者的还是评论别人的评论的;oldComment就是就评论者的名字(实际储存的时候应该是id);chosedIndex是被点击的评论的index。
canelCommit是监听到取消评论事件,这里是为了如果了点击了别人的评论但是突然我就是想变评论作者用的。所以设type=0;
changCommmer是监听到点击了别人评论想回复评论的。即type=1.
addComment就是监听添加评论事件的。根据type的值,push相应的数组。这里还要记得跟数据库那个对接。传数据有两种方法,这里是根据type的不同分两个url传还是一个,取决于表的设计。待我明天好好设计表后,加入http请求,完成这个评论功能。
要期末了。真的怕挂科。
补充一下:
由于第一次自己设计数据库的表结构,所以很有问题。
更新一下,正确的表结构应该是每条评论都有自己的id,有一个parentId属性默认为null,如果是直接评论的话,parentId值为null,如果是回复别人的评论的话,parentId是那条评论的id。最后查出一条条数据后,再根据里面的是否有parentId等再组件这个obj,传到前端。如果直接组这个obj的话会for循环3次,所以。。。打算用一用数据结构里的散列,不用for循环这么多次。这周末搞定这个,下篇文章就是它了。
然而当我思考了下后。如果单单用散列的话,就不能根据时间来排序了。因为散列是根据id%length的值来插入的,所以没了时间排序。如果直接根据查数据库返回的数组组合这个obj的话,肯定是早插入的id靠前所以有时间顺序。这个数据结构的问题还真不简单啊。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Vue.js文章评论
# Vue.js回复评论
# Vue.js评论
# vue实现发表评论功能
# vue实现文章评论和回复列表
# VUE+Java实现评论回复功能
# Vue组件实现评论区功能
# vue开发实现评论列表
# vue实现评论列表
# Vue实现简单的发表评论功能
# vue实现评论列表功能
# Vuepress 搭建带评论功能的静态博客的实现
# vue组件实现发表评论功能
# 绑定
# 都是
# 暂无
# 我来
# 遍历
# 数据结构
# 那条
# 每条
# 第一篇
# 文本框
# 自己的
# 应该是
# 是一个
# 我是
# 他们的
# 几个
# 都有
# 很好
# 可以用
# 很有
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
C#如何调用原生C++ COM对象详解
如何快速生成凡客建站的专业级图册?
如何用AI帮你把自己的生活经历写成一个有趣的故事?
Angular 表单中正确绑定输入值以确保提交与验证正常工作
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
java获取注册ip实例
Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置
Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】
Laravel如何实现用户角色和权限系统_Laravel角色权限管理机制
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】
移动端脚本框架Hammer.js
如何在Windows虚拟主机上快速搭建网站?
Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
Laravel怎么连接多个数据库_Laravel多数据库连接配置
如何在阿里云虚拟服务器快速搭建网站?
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
如何为不同团队 ID 动态生成多个独立按钮
如何破解联通资金短缺导致的基站建设难题?
Laravel distinct去重查询_Laravel Eloquent去重方法
网站制作软件有哪些,制图软件有哪些?
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
Laravel模型事件有哪些_Laravel Model Event生命周期详解
使用豆包 AI 辅助进行简单网页 HTML 结构设计
如何在阿里云通过域名搭建网站?
黑客入侵网站服务器的常见手法有哪些?
MySQL查询结果复制到新表的方法(更新、插入)
Android滚轮选择时间控件使用详解
如何用花生壳三步快速搭建专属网站?
Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】
Laravel如何使用Blade组件和插槽?(Component代码示例)
Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能
EditPlus 正则表达式 实战(3)
Laravel中间件如何使用_Laravel自定义中间件实现权限控制
高端建站三要素:定制模板、企业官网与响应式设计优化
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
南京网站制作费用,南京远驱官方网站?
合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?
个人网站制作流程图片大全,个人网站如何注销?
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
Android使用GridView实现日历的简单功能
如何在阿里云完成域名注册与建站?
Laravel如何处理CORS跨域请求?(配置示例)
如何在香港服务器上快速搭建免备案网站?
微信小程序 input输入框控件详解及实例(多种示例)
Laravel如何处理异常和错误?(Handler示例)
如何快速搭建高效简练网站?
如何快速生成橙子建站落地页链接?
微信小程序制作网站有哪些,微信小程序需要做网站吗?

