Vue评论组件案例
最近学习了Vue前端框架,在这里记录一下组件的用法,我自己试着写了一个评论的组件,大神看到勿喷,欢迎提出宝贵意见。
首先看一下效果图
用到的文件有:
<link rel="stylesheet" href="../js/bootstrap/dist/css/bootstrap.min.css">
<!-- Ionicons -->
<link rel="stylesheet" href="../js/Ionicons/css/ionicons.min.css">
<!-- jQuery 3 -->
<script src="../js/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 -->
<script src="../js/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- vue -->
<script src="../js/vue.js"></script>
demo下载地址:https://download.csdn.net/download/qingchundaima/10842714
话不多说直接上代码,基本注释我都写全了,这里我没有将js和html文件分开直接在html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="../js/bootstrap/dist/css/bootstrap.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="../js/Ionicons/css/ionicons.min.css"> <!-- jQuery 3 --> <script src="../js/jquery/dist/jquery.min.js"></script> <!-- Bootstrap 3.3.7 --> <script src="../js/bootstrap/dist/js/bootstrap.min.js"></script> <!-- vue --> <script src="../js/vue.js"></script> <style> [v-cloak] { display: none } .tb_comment{ width: 100%; /* border: 1px solid; */ } .tb_comment img{ width:64px; height:64px; } .tb_user{ width: 80px; } /* 用户评论内容展示 */ .div_comment_content{ padding: 6px 12px; border: 1px solid #d2d6de; background-color: #f0f8ff; } </style> </head> <body> <div class="row" id="app" v-cloak> <div class='row'> <div class="col-md-3"></div> <div class="col-md-6"> <!-- comment_item:传递给子组件数据 comment_data:父组件里定义的数据 --> <!-- id子父组件里我都定义成id----当前评论资源id --> <!-- prentsendcomment:在子组件里调用父组件发表方法的名称 sendcomment:父组件里发表方法 --> <!-- prentsendsupport:子组件里调用父组件点赞方法名称 sendsupport:父组件里点赞方法 --> <!-- prentsendopposition:子组件里调用父组件反对方法名称 sendopposition:父组件里反对方法 --> <temp_comment v-bind:comment_item="comment_data" v-bind:id="id" @prentsendcomment="sendcomment" @prentsendsupport="sendsupport" @prentsendopposition="sendopposition"> </temp_comment> </div> <div class="col-md-3"></div> </div> </div> <!-- 评论组件html代码结构 --> <template id='tp_comment'> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">欢迎您发表评论</h3> </div> <div class="panel-body form-check-inline"> <label style="color:gray">请勿发表与本片无关的主题,评论需要审核</label> <textarea class="form-control" style="resize:none;" rows="5" placeholder="说点什么吧..." maxlength="20" v-model="input_comment"> </textarea> <span class="pull-right">还能输入<b style="color:red">{{surplus}}</b>/{{total}}</span><br> <input type="button" class="pull-right btn btn-primary" value="发表" @click="btnsend"> <div v-for="item in comment_item" :key="item.Id"> <table class="tb_comment table table-condensed"> <tbody> <tr> <td class="tb_user"> <img class="img-circle" v-bind:src="item.PortraitUrl"> </td> <td> <p>{{item.NickName}} <i class="glyphicon glyphicon-time"></i> {{item.CreateTime|date}} <span class="pull-right"> <a href="#" @click.prevent="btnsupport(item.Id)"> <i class=" glyphicon glyphicon-thumbs-up"></i> ({{item.SupportNum}})</a> <a href="#" @click.prevent="btnopposition(item.Id)"><i class=" glyphicon glyphicon-thumbs-down"></i> ({{item.OppositionNum}})</a> </span> </p> <div class='div_comment_content'> {{item.CommentContent}} </div> </td> </tr> </tbody> </table> </div> <table class="tb_comment table table-condensed" v-if="comment_item.length==0"> <tbody> <tr> <td class="text-muted" style="width:100%"> <h4>暂无评论...</h4> </td> </tr> </tbody> </table> </div> </div> </template> <script> window.onload = function (ev) { // 定义评论组件 var temp_comment = { template: '#tp_comment', // 组件里的数据必须是方法返回。 data: function () { return { input_comment: '',// 输入的评论 total: 200,// 评论可输入总字数 } }, // 父组件传递的消息列表 props: ['comment_item', 'id'], // 计算属性 computed: { // 计算剩余可输入字数 surplus: function () { return this.total - this.input_comment.length; }, }, // 自定义过滤器 filters: { // 时间过滤器 "date": function (d) { var newdate = new Date(d); y = newdate.getFullYear(); m = (newdate.getMonth() + 1).toString().padStart(2, '0'); d = newdate.getDay().toString().padStart(2, '0'); hh = newdate.getHours().toString().padStart(2, '0'); mm = newdate.getMinutes().toString().padStart(2, '0'); ss = newdate.getSeconds().toString().padStart(2, '0'); return y + '-' + m + '-' + d + ' ' + hh + ':' + mm + ':' + ss } }, // 方法 methods: { // 父组件传入的发表评论方法,由子组件调用父组件发表评论方法 btnsend: function () { // 调用父组件方法。 this.$emit('prentsendcomment', this.id, this.input_comment) }, // 评论点赞 btnsupport: function (id) { // 调用父组件方法。 this.$emit('prentsendsupport', id) }, // 评论反对 btnopposition: function (id) { // 调用父组件方法。 this.$emit('prentsendopposition', id) } } } var vm = new Vue({ el: '#app', data: { id: 12, // 测试数据 comment_data: [ { Id: 1, PortraitUrl: "../images/user2-160x160.jpg", NickName: '那年初夏', CommentContent: '劝君更敬一杯酒', SupportNum: 14, OppositionNum: 323, CreateTime: new Date() }, { Id: 2, PortraitUrl: "../images/user2-160x160.jpg", NickName: '列夫托尔斯泰', CommentContent: '这个部电影指的我们去好好看看。', SupportNum: 2312, OppositionNum: 33, CreateTime: new Date() }, { Id: 3, PortraitUrl: "../images/user2-160x160.jpg", NickName: '小怪兽', CommentContent: '千万不要下载,千万不要下载,千万不要下载,我活了34年,这种烂片,第一次见难道比纯洁心灵还要烂》?', SupportNum: 23, OppositionNum: 43, CreateTime: new Date() }, { Id: 4, PortraitUrl: "../images/user2-160x160.jpg", NickName: '帅大叔', CommentContent: '到菜市场买菜,看到一个孩子在看摊,我问:“一只鸡多少钱?” 那孩子回答:“23。” 我又问:“两只鸡多少钱?” 孩子愣了一下,一时间没算过来,急中生智大吼一声:“一次只能买一只!”', SupportNum: 56, OppositionNum: 55, CreateTime: new Date() }, { Id: 5, PortraitUrl: "../images/user2-160x160.jpg", NickName: '夏末', CommentContent: '版权归作者所有,任何形式转载请联系作者。作者:电影幕后故事(来自豆瓣)来源:https://movie.douban.com/review/9666136/郭敬明当作家远不如当商人成功。当作家写出来的那些不知所云、虚到不行的句子只能骗一骗心智不成熟的小孩子;但做商人时所展现出来的精明与虚伪倒是能骗过不少人。我指的就这部披着“反校园霸凌”外衣,实则还是矫情、无病呻吟的电影。', SupportNum: 78, OppositionNum: 23, CreateTime: new Date() }, { Id: 6, PortraitUrl: "../images/user2-160x160.jpg", NickName: '罗罔极', CommentContent: '前阵子,我犯了个错。 我在文章里说,当下的大陆喜剧,有两大派系分庭抗礼。 一派是徐峥宁浩,其作品核心偏于人间悲剧; 一派是开心麻花,其作品核心偏于纯粹喜剧。 没想到,现在又杀出个程咬金。 八年酝酿,慢工打磨。 导演、编剧:黄渤。 这一出手,就震惊四座—— 《一出好... ', SupportNum: 332, OppositionNum: 33, CreateTime: new Date() }, ] }, // 注册组件 components: { 'temp_comment': temp_comment, }, // 方法 methods: { getdata: function () { var list = JSON.parse(localStorage.getItem('cmts') || '[]') this.list = list; }, // 由子组件调用后传入评论资源的id和内容 sendcomment: function (id, content) { alert(id + '------' + content) }, // 子组件触发点赞 sendsupport: function (id) { alert(id) }, // 子组件触发反对 sendopposition: function (id) { alert(id) } }, beforeCreate() { // 这时候data 和methods 都还没有被初始化,所以访问不到getdata }, created() { this.getdata(); } }) }; </script> </body> </html>