vue2.0結(jié)合DataTable插件實(shí)現(xiàn)表格動(dòng)態(tài)刷新的方法詳解
本文實(shí)例講述了vue2.0結(jié)合DataTable插件實(shí)現(xiàn)表格動(dòng)態(tài)刷新的方法。分享給大家供大家參考,具體如下:
產(chǎn)品提出的需求是這樣的,很普通的一個(gè)統(tǒng)計(jì)server端task完成率和狀態(tài)的表格,要自動(dòng)刷新其中的數(shù)據(jù),并且當(dāng)單個(gè)task完成的時(shí)候report給server端,看起來(lái)好easy好easy的一個(gè)需求??!且聽(tīng)我說(shuō)完哈!
我這邊使用的是框架是vue,表格自然用v-for渲染,然后我們這邊分頁(yè)搜索神馬的都是前端弄,也就是說(shuō)后端只管把一大坨數(shù)據(jù)塞到前端,然后前端自己組裝分頁(yè)器和完成模糊搜索,所以啊,我之前用的是DataTable這個(gè)插件,組裝好的表格效果如下,看著沒(méi)毛病哈!

可是涉及到自動(dòng)刷新就有問(wèn)題了,因?yàn)槊看潍@取數(shù)據(jù)都是全量數(shù)據(jù),用dataTable組裝表格的話,就必須要組裝好的表格destroy掉,然后再v-for再DataTable()組裝..頁(yè)面會(huì)一直一直閃!體驗(yàn)好差的說(shuō)!
我只想出了一個(gè)比較笨的方法解決這個(gè)局部刷新的問(wèn)題,大家要是有更好的方法一定要告訴我!!上代碼!
1.v-for只渲染不變的數(shù)據(jù),比如名字備注之類的,一直刷新的字段比如狀態(tài)和完成率都為空,就這樣,只用DataTable首次渲染表格
2.setRefresh是一個(gè)定時(shí)器,每隔1s就遞歸調(diào)用一次自己,query全量數(shù)據(jù),存放到originTableList里
3.updateRefreshStatus是用原生的js去獲取每行的dom,然后innerText去改變其值
4.reportTaskComplete是當(dāng)當(dāng)前這個(gè)task完成率達(dá)到100%就匯報(bào)給server
5.checkTaskRefresh是遞歸檢查所有的任務(wù),把完成的任務(wù)放到completeTaskList,如果全都完成了就把定時(shí)器清除掉
6.beforeRouteLeave是vue router的方法,在離開(kāi)路由之后清除計(jì)時(shí)器
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">自動(dòng)刷新開(kāi)關(guān):</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()">添加任務(wù)</button>
</div>
<div class="col-xs-12 main-table-wrapper">
<h4 class="page-header">點(diǎn)播刷新任務(wù)數(shù)據(jù)表格 <!-- <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>狀態(tài)</th>
<th>完成率</th>
<th>創(chuàng)建時(shí)間</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,// 開(kāi)啟分頁(yè)
"pageLength": 10,//每頁(yè)顯示數(shù)量
"lengthChange": true,//是否允許用戶改變表格每頁(yè)顯示的記錄數(shù)
"searching": true,//搜索
"ordering": true,//排序
"info": true,//左下角 從 1 到 5 /共 23 條數(shù)據(jù)
"autoWidth": true,
// "scrollX": "100%",//表格的寬度
// "scrollY": "200px",//表格的高度
"scrollXInner": "100%",//表格的內(nèi)容寬度
// "bScrollCollapse":true,//當(dāng)顯示的數(shù)據(jù)不足以支撐表格的默認(rèn)的高度時(shí),依然顯示縱向的滾動(dòng)條。(默認(rèn)是false)
"aaSorting": [
[3, 'asc']
],
"language": {
"sInfoEmpty": "沒(méi)有數(shù)據(jù)",
"sZeroRecords": "沒(méi)有查找到滿足條件的數(shù)據(jù)",
"sInfo": "從 _START_ 到 _END_ /共 _TOTAL_ 條數(shù)據(jù)",
"sLengthMenu": "每頁(yè)顯示 _MENU_ 條記錄",
"sInfoFiltered": "(從 _MAX_ 條數(shù)據(jù)中檢索)",
"oPaginate": {
"sFirst": "首頁(yè)",
"sPrevious": "前一頁(yè)",
"sNext": "后一頁(yè)",
"sLast": "尾頁(yè)"
}
},
});
},
initQuery: function(){
// status 和 rate兩個(gè)字段是實(shí)時(shí)刷新的
// dataTable摧毀和tableList賦值都砸在promise里完成
// tableList只初始化的時(shí)候賦值一次 然后就不動(dòng)了 用原生js去改變表格內(nèi)的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全部執(zhí)行完畢:' + JSON.stringify(result)); // ["Hello", "World"]
//renderTable函數(shù)只在首次進(jìn)入頁(yè)面時(shí)調(diào)用 1.毀掉dataTable插件 2.加載一次表格更新?tīng)顟B(tài)和完成率 3.調(diào)用自動(dòng)刷新
mySelf.renderTable();
mySelf.updateRefreshStatus();
mySelf.setRefresh();
});
},
switchRefreshStatus: function(){
let mySelf = this;
let status = mySelf.refresh.status;
let text = (status==true)?'關(guān)閉':'開(kāi)啟';
let confirmCallback = null;
if (status==true){
confirmCallback = function(){
mySelf.refresh.status = false;
}
}
else{
confirmCallback = function(){
mySelf.refresh.status = true;
mySelf.setRefresh();
}
}
util.showConfirm('確認(rèn)要' + text + '自動(dòng)刷新么?',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;
//當(dāng)前task完成 report給后端
if (Number.parseInt(completeRate) == 1){
// 若任務(wù)完成列表 沒(méi)有這個(gè)TaskId 則發(fā)送請(qǐng)求
if (!completeTaskList.includes(item.id)){
console.log(item.id + "任務(wù)完成了!并且不存在于任務(wù)完成列表,現(xiàn)在發(fā)送完成請(qǐng)求!");
mySelf.reportTaskComplete(item.id);
mySelf.refresh.completeTaskList.push(item.id);
}
}
else{
taskAllComplete = false;
}
});
if(taskAllComplete){
console.log('全部任務(wù)都完成了!')
return true;
}
return false;
},
setRefresh: function(){
let mySelf = this;
let status = mySelf.refresh.status;
let interval = mySelf.refresh.interval;
// 如果所有任務(wù)都完成了 則停止發(fā)送ajax請(qǐng)求 并更新最后一次
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全部執(zhí)行完畢:' + JSON.stringify(result)); // ["Hello", "World"]
mySelf.updateRefreshStatus();
mySelf.setRefresh();
});
},interval);
}
else{
mySelf.clearRefresh();
}
},
updateRefreshStatus: function(){
console.log('更新刷新?tīng)顟B(tài)')
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)
// 獲取當(dāng)前頁(yè)面展示的所有tr
let trDom = mainTable.getElementsByClassName(trClassName)[0];
// console.log(trDom)
// 局部刷新個(gè)別字段
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',"接口調(diào)用失敗,報(bào)錯(cuò)信息為:" + 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();
},
整體的效果如下,功能整體是實(shí)現(xiàn)了,但是感覺(jué)好笨的說(shuō),大家要是有好辦法一定要告訴我哈??!

希望本文所述對(duì)大家vue.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作
這篇文章主要介紹了vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Vue3中關(guān)于getCurrentInstance的大坑及解決
這篇文章主要介紹了Vue3中關(guān)于getCurrentInstance的大坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Vue利用computed配合watch實(shí)現(xiàn)監(jiān)聽(tīng)多個(gè)屬性的變化
這篇文章主要給大家介紹了在Vue中巧用computed配合watch實(shí)現(xiàn)監(jiān)聽(tīng)多個(gè)屬性的變化的方法,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10
vue打包通過(guò)image-webpack-loader插件對(duì)圖片壓縮優(yōu)化操作
這篇文章主要介紹了vue打包通過(guò)image-webpack-loader插件對(duì)圖片壓縮優(yōu)化操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Vue.js組件使用開(kāi)發(fā)實(shí)例教程
Vue.js的組件可以理解為預(yù)先定義好了行為的ViewModel類。這篇文章主要介紹了Vue.js組件使用開(kāi)發(fā)實(shí)例教程的相關(guān)資料,需要的朋友可以參考下2016-11-11
使用Element實(shí)現(xiàn)表格表頭添加搜索圖標(biāo)和功能
這篇文章主要介紹了使用Element實(shí)現(xiàn)表格表頭添加搜索圖標(biāo)和功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
element ui表格實(shí)現(xiàn)下拉篩選功能
這篇文章主要為大家詳細(xì)介紹了element ui表格實(shí)現(xiàn)下拉篩選功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11

