Vue.js實現(xiàn)文章評論和回復(fù)評論功能
本來想把這個頁面用jade渲染出來、評論部分用vue,但是想了想覺得麻煩,最后還是整個用vue的組件搞定他吧。
先上在線demo:http://jsbin.com/ceqifo/1/edit?js,output
再上效果圖

可直接評論,點擊別人的評論能回復(fù)別人的評論。
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>
數(shù)據(jù)全都由根組件綁定下去的。這里還監(jiān)聽了幾個事件。
<article-content是文章內(nèi)容的組件,沒啥好講的,直接把數(shù)據(jù)綁定進去子組件就行了。這里我是直接綁定一個obj而不是把標題、時間等等詳細的信息分別綁定進去。因為直接綁定一個對象,子組件可以用.的方式很好的調(diào)用,比分開寫好多了。
<article-content組件–文本
然后先說個簡單點的,<comment-textarea>,文本框的那個組件。
Vue.component('commentTextarea',{
template:'\
<div class="commentBox">\
<h3>發(fā)表評論</h3>\
<b v-if="type">你回復(fù) {{name}}</b>\
<textarea name="" value="請?zhí)顚懺u論內(nèi)容" v-model="commentText"></textarea>\
<button class="btn" @click="addComment">發(fā)表</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是如果點擊了別人的評論,會顯示 ”你回復(fù)xxx “ 的提示框,這個因為跨了組件通信而且兩組件不是父子組件但是是兄弟組件,我把他們的通信掛在了父組件的一個屬性上,實現(xiàn)通信。
文本框內(nèi)的內(nèi)容用一個v-model雙向綁定,如果點擊了確定,就觸發(fā)一個 addComment事件并把文本內(nèi)容傳給父組件,父組件會監(jiān)聽事件。
commemt-content組件–評論內(nèi)容
先來確定json格式
comment: [
{
name: "有毒的黃同學", //評論人名字
time: "2016-08-17",
content: "好,講得非常好,good",
reply: [ //回復(fù)評論的信息,是一個數(shù)組,如果沒內(nèi)容就是一個空數(shù)組
{
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">暫無評論,我來發(fā)表第一篇評論!</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}} 回復(fù) {{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);
}
}
});
如果沒有內(nèi)容,則顯示 “暫無評論,我來發(fā)表第一篇評論!”。如果有內(nèi)容就開始遍歷。因為點擊評論要知道第幾條,所以每條評論要綁一個v-bind:index="index"
到了二次評論那塊,還是遍歷reply數(shù)組,綁定該綁定的。因為就算點擊內(nèi)容,也是加到那條一級評論的最下面,所以兩個點擊事件我都是綁定了同一個事件。只是傳進去的名字不一樣而已,后面那個index都是一級評論的index。
changeCommenter事件觸發(fā)了change,父組件監(jiān)聽,執(zhí)行相應(yīng)行為。
父組件
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: [] //評論內(nèi)容
},
methods: {
//添加評論
addComment: function(data) {
if(this.type == 0) {
this.comment.push({
name: 'session',
time: getTime(),
content: data,
reply: []
});
//服務(wù)器端
}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;
}
},
//監(jiān)聽到了點擊了別人的評論
changCommmer: function(name,index) {
this.oldComment = name;
this.chosedIndex = index;
this.type = 1;
},
//監(jiān)聽到了取消評論
canelCommit: function() {
this.type = 0;
}
}
})
data那里。。。實在是取名困難癥啊。。。commenter是當前登錄名,這里到時候會session里拿;type就是看到底是評論作者的還是評論別人的評論的;oldComment就是就評論者的名字(實際儲存的時候應(yīng)該是id);chosedIndex是被點擊的評論的index。
canelCommit是監(jiān)聽到取消評論事件,這里是為了如果了點擊了別人的評論但是突然我就是想變評論作者用的。所以設(shè)type=0;
changCommmer是監(jiān)聽到點擊了別人評論想回復(fù)評論的。即type=1.
addComment就是監(jiān)聽添加評論事件的。根據(jù)type的值,push相應(yīng)的數(shù)組。這里還要記得跟數(shù)據(jù)庫那個對接。傳數(shù)據(jù)有兩種方法,這里是根據(jù)type的不同分兩個url傳還是一個,取決于表的設(shè)計。待我明天好好設(shè)計表后,加入http請求,完成這個評論功能。
要期末了。真的怕掛科。
補充一下:
由于第一次自己設(shè)計數(shù)據(jù)庫的表結(jié)構(gòu),所以很有問題。
更新一下,正確的表結(jié)構(gòu)應(yīng)該是每條評論都有自己的id,有一個parentId屬性默認為null,如果是直接評論的話,parentId值為null,如果是回復(fù)別人的評論的話,parentId是那條評論的id。最后查出一條條數(shù)據(jù)后,再根據(jù)里面的是否有parentId等再組件這個obj,傳到前端。如果直接組這個obj的話會for循環(huán)3次,所以。。。打算用一用數(shù)據(jù)結(jié)構(gòu)里的散列,不用for循環(huán)這么多次。這周末搞定這個,下篇文章就是它了。
然而當我思考了下后。如果單單用散列的話,就不能根據(jù)時間來排序了。因為散列是根據(jù)id%length的值來插入的,所以沒了時間排序。如果直接根據(jù)查數(shù)據(jù)庫返回的數(shù)組組合這個obj的話,肯定是早插入的id靠前所以有時間順序。這個數(shù)據(jù)結(jié)構(gòu)的問題還真不簡單啊。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
element el-tooltip動態(tài)顯示隱藏(有省略號顯示,沒有省略號不顯示)
本文主要介紹了element el-tooltip動態(tài)顯示隱藏,主要實現(xiàn)有省略號顯示,沒有省略號不顯示,具有一定的參考價值,感興趣的可以了解一下2023-09-09
Element 默認勾選表格 toggleRowSelection的實現(xiàn)
這篇文章主要介紹了Element 默認勾選表格 toggleRowSelection的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09
vue如何將html內(nèi)容轉(zhuǎn)為圖片并下載到本地
這篇文章主要介紹了vue如何將html內(nèi)容轉(zhuǎn)為圖片并下載到本地,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
vue3實現(xiàn)模擬地圖站點名稱按需顯示的功能(車輛模擬地圖)
最近在做車輛模擬地圖,在實現(xiàn)控制站點名稱按需顯示,下面通過本文給大家分享vue3實現(xiàn)模擬地圖站點名稱按需顯示的功能,感興趣的朋友跟隨小編一起看看吧2024-06-06
詳解利用eventemitter2實現(xiàn)Vue組件通信
這篇文章主要介紹了詳解利用eventemitter2實現(xiàn)Vue組件通信,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11

