vue2.0结合DataTable插件实现表格动态刷新的方法详解
本文实例讲述了vue2.0结合datatable插件实现表格动态刷新的方法。分享给大家供大家参考,具体如下:
产品提出的需求是这样的,很普通的一个统计server端task完成率和状态的表格,要自动刷新其中的数据,并且当单个task完成的时候report给server端,看起来好easy好easy的一个需求啊!且听我说完哈!
我这边使用的是框架是vue,表格自然用v-for渲染,然后我们这边分页搜索神马的都是前端弄,也就是说后端只管把一大坨数据塞到前端,然后前端自己组装分页器和完成模糊搜索,所以啊,我之前用的是datatable这个插件,组装好的表格效果如下,看着没毛病哈!
可是涉及到自动刷新就有问题了,因为每次获取数据都是全量数据,用datatable组装表格的话,就必须要组装好的表格destroy掉,然后再v-for再datatable()组装..页面会一直一直闪!体验好差的说!
我只想出了一个比较笨的方法解决这个局部刷新的问题,大家要是有更好的方法一定要告诉我!!上代码!
1.v-for只渲染不变的数据,比如名字备注之类的,一直刷新的字段比如状态和完成率都为空,就这样,只用datatable首次渲染表格
2.setrefresh是一个定时器,每隔1s就递归调用一次自己,query全量数据,存放到origintablelist里
3.updaterefreshstatus是用原生的js去获取每行的dom,然后innertext去改变其值
4.reporttaskcomplete是当当前这个task完成率达到100%就汇报给server
5.checktaskrefresh是递归检查所有的任务,把完成的任务放到completetasklist,如果全都完成了就把定时器清除掉
6.beforerouteleave是vue router的方法,在离开路由之后清除计时器
template
<template> <div class="row"> <loadinghourglass></loadinghourglass> <div class="col-xs-12 top-offset-15 bottom-offset-15"> <div> <strong class="pull-left line-height-24 right-offset-15">自动刷新开关:</strong> <iphoneswitcher v-bind:status="refresh.status" v-bind:canswitch="false" v-bind:callbackname="'switchrefreshstatus'"></iphoneswitcher> </div> <button type="button" class="btn btn-sm btn-primary pull-right" v-on:click="editrecord()">添加任务</button> </div> <div class="col-xs-12 main-table-wrapper"> <h4 class="page-header">点播刷新任务数据表格 <!-- <small>secondary text</small> --></h4> <!-- <p>123</p> --> <table class="table table-striped table-hover table-bordered" id="main-table"> <thead> <tr> <th>名称</th> <th>状态</th> <th>完成率</th> <th>创建时间</th> <th>备注</th> <th>操作</th> </tr> </thead> <tbody><!-- v-bind:class=" (item.completecount/item.total=='1')?'text-success':'text-danger' " --> <tr v-for="item in tablelist" v-bind:class="'id-' + item.id"> <td>{{ item.file_name }}</td> <!-- {{ item.status | statusfilter }} --> <td class="status"></td> <!-- v-bind:class=" (item.completecount/item.total=='1')?'text-success':'text-danger' " --> <!-- {{ item.completerate }} --> <td class="rate"></td> <td>{{ item.create_time }}</td> <td>{{ item.description }}</td> <td> <button type="button" class="btn btn-primary btn-xs" v-on:click="showdetailmodal(item.id,item.file_name)">详情</button> <!-- <button type="button" class="btn btn-danger btn-xs" v-on:click="test()">test</button> --> </td> </tr> </tbody> </table> </div> </div> </template>
js
methods: { initrecordtable: function(){ $('#main-table').datatable({ "paging": true,// 开启分页 "pagelength": 10,//每页显示数量 "lengthchange": true,//是否允许用户改变表格每页显示的记录数 "searching": true,//搜索 "ordering": true,//排序 "info": true,//左下角 从 1 到 5 /共 23 条数据 "autowidth": true, // "scrollx": "100%",//表格的宽度 // "scrolly": "200px",//表格的高度 "scrollxinner": "100%",//表格的内容宽度 // "bscrollcollapse":true,//当显示的数据不足以支撑表格的默认的高度时,依然显示纵向的滚动条。(默认是false) "aasorting": [ [3, 'asc'] ], "language": { "sinfoempty": "没有数据", "szerorecords": "没有查找到满足条件的数据", "sinfo": "从 _start_ 到 _end_ /共 _total_ 条数据", "slengthmenu": "每页显示 _menu_ 条记录", "sinfofiltered": "(从 _max_ 条数据中检索)", "opaginate": { "sfirst": "首页", "sprevious": "前一页", "snext": "后一页", "slast": "尾页" } }, }); }, initquery: function(){ // status 和 rate两个字段是实时刷新的 // datatable摧毁和tablelist赋值都砸在promise里完成 // tablelist只初始化的时候赋值一次 然后就不动了 用原生js去改变表格内的status字段 let myself = this; let callback = function(){ if($('#main-table').datatable()){ $('#main-table').datatable().destroy() } myself.tablelist = util.deepclone(myself.origintablelist); } let querytablepromise = myself.querytable(callback); let promiselist = []; myself.clearrefresh(); promiselist.push(querytablepromise); promise.all(promiselist).then(function (result) { console.log('ajax全部执行完毕:' + json.stringify(result)); // ["hello", "world"] //rendertable函数只在首次进入页面时调用 1.毁掉datatable插件 2.加载一次表格更新状态和完成率 3.调用自动刷新 myself.rendertable(); myself.updaterefreshstatus(); myself.setrefresh(); }); }, switchrefreshstatus: function(){ let myself = this; let status = myself.refresh.status; let text = (status==true)?'关闭':'开启'; let confirmcallback = null; if (status==true){ confirmcallback = function(){ myself.refresh.status = false; } } else{ confirmcallback = function(){ myself.refresh.status = true; myself.setrefresh(); } } util.showconfirm('确认要' + text + '自动刷新么?',confirmcallback); }, checktaskrefresh: function(){ let myself = this; let origintablelist = myself.origintablelist; let taskallcomplete = true; // console.log(json.stringify(myself.origintablelist)); origintablelist.foreach(function(item,index,array){ let completetasklist = myself.refresh.completetasklist; let completerate = item.completerate; //当前task完成 report给后端 if (number.parseint(completerate) == 1){ // 若任务完成列表 没有这个taskid 则发送请求 if (!completetasklist.includes(item.id)){ console.log(item.id + "任务完成了!并且不存在于任务完成列表,现在发送完成请求!"); myself.reporttaskcomplete(item.id); myself.refresh.completetasklist.push(item.id); } } else{ taskallcomplete = false; } }); if(taskallcomplete){ console.log('全部任务都完成了!') return true; } return false; }, setrefresh: function(){ let myself = this; let status = myself.refresh.status; let interval = myself.refresh.interval; // 如果所有任务都完成了 则停止发送ajax请求 并更新最后一次 if (myself.checktaskrefresh()){ console.log('更新最后一次表格!') myself.updaterefreshstatus(); return false; } // console.log('refresh') if (status){ myself.refresh.timer = settimeout(function(){ let querytablepromise = myself.querytable(); let promiselist = []; promiselist.push(querytablepromise); promise.all(promiselist).then(function (result) { console.log('ajax全部执行完毕:' + json.stringify(result)); // ["hello", "world"] myself.updaterefreshstatus(); myself.setrefresh(); }); },interval); } else{ myself.clearrefresh(); } }, updaterefreshstatus: function(){ console.log('更新刷新状态') let myself = this; let maintable = document.getelementbyid("main-table"); let origintablelist = myself.origintablelist; origintablelist.foreach(function(item,index,array){ let trclassname = "id-" + item.id; // console.log(trclassname) // 获取当前页面展示的所有tr let trdom = maintable.getelementsbyclassname(trclassname)[0]; // console.log(trdom) // 局部刷新个别字段 if (trdom){ let tdrate = trdom.getelementsbyclassname("rate")[0]; let tdstatus = trdom.getelementsbyclassname("status")[0]; tdrate.innertext = item.completerate; tdrate.classname = (item.status == "1")?"text-info rate":((item.status == "2")?"text-success rate":"text-danger rate"); tdstatus.innertext = (item.status == "1")?"刷新中":((item.status == "2")?"刷新完成":"刷新失败"); tdstatus.classname = (item.status == "1")?"text-info status":((item.status == "2")?"text-success status":"text-danger status"); } }); }, clearrefresh: function(){ let myself = this; console.log('clear timer'); cleartimeout(myself.refresh.timer); }, querytable: function(callback){ let myself = this; let promise = new promise(function (resolve, reject) { let url = pars.domain + "/api.php?action=xxxxxxx&t=" + (new date).gettime(); $.get(url, function(res) { if (res.code == 0) { let resdata = res.list; resdata.foreach(function(item,index,array){ let info = item.info; let completecount = info.completecount; let total = info.count; item.completerate = ((completecount/total)*100).tofixed(2) + "%"; }); // console.log(json.stringify(resdata)) myself.origintablelist = resdata; if (callback){ callback(); } resolve('querytable完成!'); } else{ util.showdialog('error',"接口调用失败,报错信息为:" + res.message); } }, "json"); }); return promise; }, rendertable: function(){ let myself = this; myself.$nexttick(function(){ myself.initrecordtable(); util.hideloading(); }) } }, beforerouteleave (to, from, next){ let myself = this; myself.clearrefresh(); next(); },
整体的效果如下,功能整体是实现了,但是感觉好笨的说,大家要是有好办法一定要告诉我哈!!
希望本文所述对大家vue.js程序设计有所帮助。