利用Vue+ElementUi實現(xiàn)評論功能
前言
這兩天在用vue重構(gòu)之前寫的一個社區(qū)博客項目,之前評論的樣式和效果都差強人意,所以仿照掘金重寫了一個評論功能(但不是完全照搬模仿)
在寫完這個功能后,由心覺得Vue真的非常好用。
話不多說,先上效果圖
代碼
html代碼:
<template> <div> <div v-clickoutside="hideReplyBtn" @click="inputFocus" class="my-reply"> <el-avatar class="header-img" :size="40" :src="myHeader"></el-avatar> <div class="reply-info" > <div tabindex="0" contenteditable="true" id="replyInput" spellcheck="false" placeholder="輸入評論..." class="reply-input" @focus="showReplyBtn" @input="onDivInput($event)" > </div> </div> <div class="reply-btn-box" v-show="btnShow"> <el-button class="reply-btn" size="medium" @click="sendComment" type="primary">發(fā)表評論</el-button> </div> </div> <div v-for="(item,i) in comments" :key="i" class="author-title reply-father"> <el-avatar class="header-img" :size="40" :src="item.headImg"></el-avatar> <div class="author-info"> <span class="author-name">{{item.name}}</span> <span class="author-time">{{item.time}}</span> </div> <div class="icon-btn"> <span @click="showReplyInput(i,item.name,item.id)"><i class="iconfont el-icon-s-comment"></i>{{item.commentNum}}</span> <i class="iconfont el-icon-caret-top"></i>{{item.like}} </div> <div class="talk-box"> <p> <span class="reply">{{item.comment}}</span> </p> </div> <div class="reply-box"> <div v-for="(reply,j) in item.reply" :key="j" class="author-title"> <el-avatar class="header-img" :size="40" :src="reply.fromHeadImg"></el-avatar> <div class="author-info"> <span class="author-name">{{reply.from}}</span> <span class="author-time">{{reply.time}}</span> </div> <div class="icon-btn"> <span @click="showReplyInput(i,reply.from,reply.id)"><i class="iconfont el-icon-s-comment"></i>{{reply.commentNum}}</span> <i class="iconfont el-icon-caret-top"></i>{{reply.like}} </div> <div class="talk-box"> <p> <span>回復 {{reply.to}}:</span> <span class="reply">{{reply.comment}}</span> </p> </div> <div class="reply-box"> </div> </div> </div> <div v-show="_inputShow(i)" class="my-reply my-comment-reply"> <el-avatar class="header-img" :size="40" :src="myHeader"></el-avatar> <div class="reply-info" > <div tabindex="0" contenteditable="true" spellcheck="false" placeholder="輸入評論..." @input="onDivInput($event)" class="reply-input reply-comment-input"></div> </div> <div class=" reply-btn-box"> <el-button class="reply-btn" size="medium" @click="sendCommentReply(i,j)" type="primary">發(fā)表評論</el-button> </div> </div> </div> </div> </template>
JS代碼如下
我把模擬的數(shù)據(jù)寫在了data里面,顯得js有點長。如果要更改數(shù)據(jù)的格式的話,記得也要改Html不然會出錯。
<script> const clickoutside = { // 初始化指令 bind(el, binding, vnode) { function documentHandler(e) { // 這里判斷點擊的元素是否是本身,是本身,則返回 if (el.contains(e.target)) { return false; } // 判斷指令中是否綁定了函數(shù) if (binding.expression) { // 如果綁定了函數(shù) 則調(diào)用那個函數(shù),此處binding.value就是handleClose方法 binding.value(e); } } // 給當前元素綁定個私有變量,方便在unbind中可以解除事件監(jiān)聽 el.vueClickOutside = documentHandler; document.addEventListener('click', documentHandler); }, update() {}, unbind(el, binding) { // 解除事件監(jiān)聽 document.removeEventListener('click', el.vueClickOutside); delete el.vueClickOutside; }, }; export default { name:'ArticleComment', data(){ return{ btnShow: false, index:'0', replyComment:'', myName:'Lana Del Rey', myHeader:'https://ae01.alicdn.com/kf/Hd60a3f7c06fd47ae85624badd32ce54dv.jpg', myId:19870621, to:'', toId:-1, comments:[ { name:'Lana Del Rey', id:19870621, headImg:'https://ae01.alicdn.com/kf/Hd60a3f7c06fd47ae85624badd32ce54dv.jpg', comment:'我發(fā)布一張新專輯Norman Fucking Rockwell,大家快來聽啊', time:'2019年9月16日 18:43', commentNum:2, like:15, inputShow:false, reply:[ { from:'Taylor Swift', fromId:19891221, fromHeadImg:'https://ae01.alicdn.com/kf/H94c78935ffa64e7e977544d19ecebf06L.jpg', to:'Lana Del Rey', toId:19870621, comment:'我很喜歡你的新專輯?。?, time:'2019年9月16日 18:43', commentNum:1, like:15, inputShow:false }, { from:'Ariana Grande', fromId:1123, fromHeadImg:'https://ae01.alicdn.com/kf/Hf6c0b4a7428b4edf866a9fbab75568e6U.jpg', to:'Lana Del Rey', toId:19870621, comment:'別忘記宣傳我們的合作單曲啊', time:'2019年9月16日 18:43', commentNum:0, like:5, inputShow:false } ] }, { name:'Taylor Swift', id:19891221, headImg:'https://ae01.alicdn.com/kf/H94c78935ffa64e7e977544d19ecebf06L.jpg', comment:'我發(fā)行了我的新專輯Lover', time:'2019年9月16日 18:43', commentNum:1, like:5, inputShow:false, reply:[ { from:'Lana Del Rey', fromId:19870621, fromHeadImg:'https://ae01.alicdn.com/kf/Hd60a3f7c06fd47ae85624badd32ce54dv.jpg', to:'Taylor Swift', toId:19891221, comment:'新專輯和speak now 一樣棒!', time:'2019年9月16日 18:43', commentNum:25, like:5, inputShow:false } ] }, { name:'Norman Fucking Rockwell', id:20190830, headImg:'https://ae01.alicdn.com/kf/Hdd856ae4c81545d2b51fa0c209f7aa28Z.jpg', comment:'Plz buy Norman Fucking Rockwell on everywhere', time:'2019年9月16日 18:43', commentNum:0, like:5, inputShow:false, reply:[] }, ] } }, directives: {clickoutside}, methods: { inputFocus(){ var replyInput = document.getElementById('replyInput'); replyInput.style.padding= "8px 8px" replyInput.style.border ="2px solid blue" replyInput.focus() }, showReplyBtn(){ this.btnShow = true }, hideReplyBtn(){ this.btnShow = false replyInput.style.padding= "10px" replyInput.style.border ="none" }, showReplyInput(i,name,id){ this.comments[this.index].inputShow = false this.index =i this.comments[i].inputShow = true this.to = name this.toId = id }, _inputShow(i){ return this.comments[i].inputShow }, sendComment(){ if(!this.replyComment){ this.$message({ showClose: true, type:'warning', message:'評論不能為空' }) }else{ let a ={} let input = document.getElementById('replyInput') let timeNow = new Date().getTime(); let time= this.dateStr(timeNow); a.name= this.myName a.comment =this.replyComment a.headImg = this.myHeader a.time = time a.commentNum = 0 a.like = 0 this.comments.push(a) this.replyComment = '' input.innerHTML = ''; } }, sendCommentReply(i,j){ if(!this.replyComment){ this.$message({ showClose: true, type:'warning', message:'評論不能為空' }) }else{ let a ={} let timeNow = new Date().getTime(); let time= this.dateStr(timeNow); a.from= this.myName a.to = this.to a.fromHeadImg = this.myHeader a.comment =this.replyComment a.time = time a.commentNum = 0 a.like = 0 this.comments[i].reply.push(a) this.replyComment = '' document.getElementsByClassName("reply-comment-input")[i].innerHTML = "" } }, onDivInput: function(e) { this.replyComment = e.target.innerHTML; }, dateStr(date){ //獲取js 時間戳 var time=new Date().getTime(); //去掉 js 時間戳后三位,與php 時間戳保持一致 time=parseInt((time-date)/1000); //存儲轉(zhuǎn)換值 var s; if(time<60*10){//十分鐘內(nèi) return '剛剛'; }else if((time<60*60)&&(time>=60*10)){ //超過十分鐘少于1小時 s = Math.floor(time/60); return s+"分鐘前"; }else if((time<60*60*24)&&(time>=60*60)){ //超過1小時少于24小時 s = Math.floor(time/60/60); return s+"小時前"; }else if((time<60*60*24*30)&&(time>=60*60*24)){ //超過1天少于30天內(nèi) s = Math.floor(time/60/60/24); return s+"天前"; }else{ //超過30天ddd var date= new Date(parseInt(date)); return date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate(); } } }, } </script>
css 代碼
<style lang="stylus" scoped> .my-reply padding 10px background-color #fafbfc .header-img display inline-block vertical-align top .reply-info display inline-block margin-left 5px width 90% @media screen and (max-width:1200px) { width 80% } .reply-input min-height 20px line-height 22px padding 10px 10px color #ccc background-color #fff border-radius 5px &:empty:before content attr(placeholder) &:focus:before content none &:focus padding 8px 8px border 2px solid blue box-shadow none outline none .reply-btn-box height 25px margin 10px 0 .reply-btn position relative float right margin-right 15px .my-comment-reply margin-left 50px .reply-input width flex .author-title:not(:last-child) border-bottom: 1px solid rgba(178,186,194,.3) .author-title padding 10px .header-img display inline-block vertical-align top .author-info display inline-block margin-left 5px width 60% height 40px line-height 20px >span display block cursor pointer overflow hidden white-space nowrap text-overflow ellipsis .author-name color #000 font-size 18px font-weight bold .author-time font-size 14px .icon-btn width 30% padding 0 !important float right @media screen and (max-width : 1200px){ width 20% padding 7px } >span cursor pointer .iconfont margin 0 5px .talk-box margin 0 50px >p margin 0 .reply font-size 16px color #000 .reply-box margin 10px 0 0 50px background-color #efefef </style>
寫在最后
如果代碼有什么問題,或者你有什么意見,歡迎大家指出。
到此這篇關于利用Vue+ElementUi實現(xiàn)評論功能的文章就介紹到這了,更多相關Vue ElementUi評論內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue+elementUI組件table實現(xiàn)前端分頁功能
這篇文章主要為大家詳細介紹了vue+elementUI組件table實現(xiàn)前端分頁功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-12-12vue中defineProperty和Proxy的區(qū)別詳解
這篇文章主要介紹了vue中defineProperty和Proxy的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11vue如何實現(xiàn)清空this.$route.query的值
這篇文章主要介紹了vue如何實現(xiàn)清空this.$route.query的值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09Vue出現(xiàn)did you register the component 
這篇文章主要介紹了Vue出現(xiàn)did you register the component correctly?解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03一文帶你深入理解Vue3中Composition API的使用
Composition API 是 Vue 3 中的一項強大功能,它改進了代碼組織和重用,使得構(gòu)建組件更加靈活和可維護,本文我們將深入探討 Composition API 的各個方面,希望對大家有所幫助2023-10-10