Vue.js实现文章评论和回复评论功能


Posted in Javascript onMay 30, 2020

本来想把这个页面用jade渲染出来、评论部分用vue,但是想了想觉得麻烦,最后还是整个用vue的组件搞定他吧。
先上在线demo:http://jsbin.com/ceqifo/1/edit?js,output

再上效果图

Vue.js实现文章评论和回复评论功能

可直接评论,点击别人的评论能回复别人的评论。

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靠前所以有时间顺序。这个数据结构的问题还真不简单啊。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Js实现网页键盘控制翻页的方法
Oct 30 Javascript
jQuery预加载图片常用方法
Jun 15 Javascript
jQuery+css实现非常漂亮的水平导航菜单效果
Jul 27 Javascript
JavaScript中Math对象的方法介绍
Jan 05 Javascript
bootstrap fileinput组件整合Springmvc上传图片到本地磁盘
May 11 Javascript
Vue.js实现按钮的动态绑定效果及实现代码
Aug 21 Javascript
使用vue自定义指令开发表单验证插件validate.js
May 23 Javascript
利用Electron简单撸一个Markdown编辑器的方法
Jun 10 Javascript
Vue 3.0 前瞻Vue Function API新特性体验
Aug 12 Javascript
详解Vue中CSS样式穿透问题
Sep 12 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
Aug 06 Javascript
Vue中使用wangeditor富文本编辑的问题
Feb 07 Vue.js
详解node.js平台下Express的session与cookie模块包的配置
Apr 26 #Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
Apr 26 #jQuery
快速使用node.js进行web开发详解
Apr 26 #Javascript
js canvas实现擦除效果示例代码
Apr 26 #Javascript
vue-cli如何快速构建vue项目
Apr 26 #Javascript
Vue制作Todo List网页
Apr 26 #Javascript
bootstrap table表格使用方法详解
Apr 26 #Javascript
You might like
vs中通过剪切板循环来循环粘贴不同内容
2011/04/30 PHP
php使用session二维数组实例
2014/11/06 PHP
PHP实现获取FLV文件的时间
2015/02/10 PHP
非常经典的PHP文件上传类分享
2016/05/15 PHP
Document对象内容集合(比较全)
2010/09/06 Javascript
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
2010/11/30 Javascript
JS实现新浪博客左侧的Blog管理菜单效果代码
2015/10/22 Javascript
正则表达式优化JSON字符串的技巧
2015/12/24 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
2016/01/03 Javascript
iOS + node.js使用Socket.IO框架进行实时通信示例
2017/04/14 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
让 babel webpack vue 配置文件支持智能提示的方法
2019/06/22 Javascript
简单了解vue中的v-if和v-show的区别
2019/10/08 Javascript
element实现合并单元格通用方法
2019/11/13 Javascript
es6函数之尾调用优化实例分析
2020/04/25 Javascript
vue 子组件修改data或调用操作
2020/08/07 Javascript
[56:48]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
[01:52]PWL S2开团时刻第四期——DOTA2成语故事
2020/12/03 DOTA
Python学习笔记_数据排序方法
2014/05/22 Python
关于Python中浮点数精度处理的技巧总结
2017/08/10 Python
Centos下实现安装Python3.6和Python2共存
2018/08/15 Python
python Django的web开发实例(入门)
2019/07/31 Python
Python编程快速上手——疯狂填词程序实现方法分析
2020/02/29 Python
ALDO美国官网:加拿大女鞋品牌
2018/12/28 全球购物
戴尔英国翻新电脑和电子产品:Dell UK Refurbished Computers
2019/07/30 全球购物
师范毕业生自荐信
2013/10/17 职场文书
应聘护理专业毕业自荐书范文
2014/02/12 职场文书
《要下雨了》教学反思
2014/02/17 职场文书
扩大国家免疫规划实施方案
2014/03/21 职场文书
民族学专业大学生职业规划范文:清晰未来的构想
2014/09/20 职场文书
道路交通事故人身损害赔偿协议书
2014/11/19 职场文书
2015年小学数学教研组工作总结
2015/05/21 职场文书
北京爱情故事观后感
2015/06/12 职场文书
信息技术教研组工作总结
2015/08/13 职场文书
CSS浮动引起的高度塌陷问题
2022/08/05 HTML / CSS
Spring Boot实现文件上传下载
2022/08/14 Java/Android