この記事では、vue2.0 と DataTable プラグインを組み合わせて動的テーブル更新を実現する方法を主に紹介し、具体的なプロジェクト例を組み合わせて、vue2.0 と DataTable プラグインを組み合わせて実行するプロセスで発生する問題を分析します。動的テーブル更新とそれに対応する必要なソリューション。友人は参照できます
この記事では、vue2.0 と DataTable プラグインを組み合わせてテーブルを動的に更新する方法について説明します。参考までに共有します:
この製品が提示する要件は次のとおりです。これは、サーバー側のタスクの完了率とステータスをカウントする非常に一般的なテーブルです。自動的に更新され、単一のタスクが完了したらレポートが報告される必要があります。サーバー側にとって、これは非常に簡単な要求のように思えます。聞いてください!
ここで使用しているのは vue である フレームワーク で、テーブルは v-for で自然にレンダリングされ、 ページング 検索 はすべてフロントエンドによって行われます。つまり、バックエンドが実行します。大量のデータが 1 つだけフロントエンドに詰め込まれ、フロントエンドがページャーを組み立ててあいまい検索を完了するため、以前は DataTable プラグインを使用していました。以下のように見えます。
しかし、自動更新に関しては問題があります。データが取得されるたびに、それが全量のデータになるためです。dataTable を使用してテーブルを組み立てる場合、組み立てられたテーブルを破棄する必要があります。次に v-for、次に DataTable() を組み立てています...ページは点滅し続けます。なんてひどい経験でしょう!
この部分的な更新の問題を解決する比較的愚かな方法を思いつきました。もっと良い方法がある場合は、教えてください。 !コードに乗ってください!
1.v-for は、名前メモなどの変更されていないデータのみをレンダリングします。ステータスや完了率など、常に更新されるフィールドは空です。このように、DataTable のみがテーブルのレンダリングに使用されます。初回
2.setRefreshはTimerであり、1秒ごとに再帰的にを呼び出し、全量のデータをクエリし、それをoriginTableList
3に保存します。 updateRefreshStatusはネイティブJSを使用して各行のDOMを取得します。 , そして innerText はその値を変更します
4 .reportTaskComplete は現在のタスクの完了率が 100% に達したときにサーバーに報告します
5. checkTaskRefresh はすべてのタスクを再帰的にチェックし、完了したタスクを completeTaskList に入れてクリアしますすべて完了したらタイマー
6. beforeRouteLeave は、ルートから抜けた後にタイマーをクリアする
template
<template> <p class="row"> <loadingHourGlass></loadingHourGlass> <p class="col-xs-12 top-offset-15 bottom-offset-15"> <p> <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> </p> <button type="button" class="btn btn-sm btn-primary pull-right" v-on:click="editRecord()">添加任务</button> </p> <p 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> </p> </p> </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(); },
全体的な効果は次のとおりです。全体的な機能は実装されています。しかし、何か良いアイデアがあれば、教えてください。 !
以上がvue2.0 と DataTable プラグインを組み合わせてテーブルを動的に更新する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。