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 相关文章推荐
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
Feb 14 Javascript
JavaScript判断一个URL链接是否有效的实现方法
Oct 08 Javascript
javascript常见用法总结
May 22 Javascript
node.js中的fs.rename方法使用说明
Dec 16 Javascript
jquery实现聚光灯效果的方法
Feb 06 Javascript
jQuery实现的超链接提示效果示例【附demo源码下载】
Sep 09 Javascript
JavaScript中Promise的使用详解
Feb 26 Javascript
js模拟百度模糊搜索的实例
Aug 04 Javascript
原生JS实现的简单小钟表功能示例
Aug 30 Javascript
微信小程序 scroll-view 实现锚点跳转功能
Dec 12 Javascript
浅谈vue 多个变量同时赋相同值互相影响
Aug 05 Javascript
利用前端HTML+CSS+JS开发简单的TODOLIST功能(记事本)
Apr 13 Javascript
详解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
hadoop常见错误以及处理方法详解
2013/06/19 PHP
解析阿里云ubuntu12.04环境下配置Apache+PHP+PHPmyadmin+MYsql
2013/06/26 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
PHP树形结构tree类用法示例
2019/02/01 PHP
php文件上传原理与实现方法详解
2019/12/20 PHP
javascript延时重复执行函数 lLoopRun.js
2007/06/29 Javascript
关于递归运算的顺序测试代码
2011/11/30 Javascript
防止浏览器记住用户名及密码的简单实用方法
2013/04/22 Javascript
jQuery焦点图切换特效插件封装实例
2013/08/18 Javascript
一个js导致的jquery失效问题的解决方法
2013/11/27 Javascript
使用 TypeScript 重新编写的 JavaScript 坦克大战游戏代码
2015/04/07 Javascript
php常见的页面跳转方法汇总
2015/04/15 Javascript
jQuery+css实现的切换图片功能代码
2016/01/27 Javascript
CascadeView级联组件实现思路详解(分离思想和单链表)
2016/04/12 Javascript
详细解读Jquery各Ajax函数($.get(),$.post(),$.ajax(),$.getJSON())
2016/08/15 Javascript
浅谈如何使用 webpack 优化资源
2017/10/20 Javascript
vue登录注册及token验证实现代码
2017/12/14 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
微信上传视频文件提示(推荐)
2018/11/22 Javascript
CryptoJS中AES实现前后端通用加解密技术
2018/12/18 Javascript
django中使用vue.js的要点总结
2019/07/07 Javascript
vue实现在线学生录入系统
2020/05/30 Javascript
python生成圆形图片的方法
2020/03/25 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
numpy数组广播的机制
2019/07/12 Python
Python把图片转化为pdf代码实例
2020/07/28 Python
python如何实现word批量转HTML
2020/09/30 Python
python如何对链表操作
2020/10/10 Python
Django用户认证系统如何实现自定义
2020/11/12 Python
pycharm Tab键设置成4个空格的操作
2021/02/26 Python
用CSS3实现无限循环的无缝滚动的实例代码
2017/07/04 HTML / CSS
HTML5中meta属性的使用方法
2016/02/29 HTML / CSS
Omio意大利:全欧洲低价大巴、火车和航班搜索和比价
2017/12/02 全球购物
幼儿教师个人总结
2015/02/05 职场文书
《索溪峪的野》教学反思
2016/02/19 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python