親測蘋果電腦,chrome瀏覽器無卡頓現象,其它瀏覽器並未測試,如遇到卡頓請備註系統和瀏覽器,方便我後續優化,謝謝vue
先看一下效果,一共1000 X 100 = 10W
個單元格基本感覺不到卡頓,並且每一個單元格點擊能夠編輯,支持固定頭和固定列jquery
Star
一下,哪裏有問題也歡迎指出,感謝筆者最近在作廣告排期功能,須要進行點位預佔,大的合同可能須要對多個資源排期,週期可能到幾年這樣,而後咱們的頁面交互是這樣git
橫向每月30個單元格,最多的3年,36個月,每行36*30=1080個單元格github
豎向100個資源,總共約️10W個單元格,而後每一個單元格里面會有一個輸入框,一個庫存總數,因此總數是20W個,內網使用,接口請求根本不是問題,能夠瀏覽器渲染就扛不住了接口回來以後會出現幾十秒的白屏,整個頁面處於卡死狀態chrome
這還不算,加載出以後頁面操做也是很是卡,滑動延遲嚴重,頁面基本處於癱瘓狀態json
以前的功能是基於jquery開發的,項目重構用的vue,UI採用了ElementUI,ElmentUI中的表格在數據量較大是有嚴重的性能問題,最直接的表現就是白屏時間較長,並且會出現渲染錯亂瀏覽器
因此就想着本身實現一個表格,解決卡頓問題bash
表格橫向按月拆分,每月份單獨一個table,月份table外層放一個佔位div,根據橫向滾動位置控制展現dom
豎向按資源拆分,一樣包裹一個佔位div,按照滾動位置動態加載,始終保持dom數量上線
方案就是點擊單元格展現輸入框,焦點丟失移除,此處的展現非display控制顯示隱藏,而是v-if控制dom是否加載
<div class="table-head">
<div class="module"
v-bind:style="{ transform: 'translateX(' + scrollLeft + 'px)' }"
v-for="(item, index) in monthData" v-bind:key="index">
<table cellspacing="0" cellpadding="0">
<thead>
<tr>
<td colspan="30">{{item.month}}</td>
</tr>
<tr>
<td width="100"
v-for="(d_item, d_index) in item.days" v-bind:key="d_index"
style="min-width:100px">{{d_item}}</td>
</tr>
</thead>
</table>
</div>
</div>
複製代碼
<div class="table-fix-cloumns">
<div class="module fix-left-top">
<table width="100" cellspacing="0" cellpadding="0">
<thead>
<tr>
<td>位置</td>
</tr>
<tr>
<td>position</td>
</tr>
</thead>
</table>
</div>
<div class="module" v-bind:style="{ transform: 'translateY(' + scrollTop + 'px)' }">
<table width="100" cellspacing="0" cellpadding="0">
<thead>
<tr v-for="(item, index) in projectData" v-bind:key="index">
<td>{{item.name}}</td>
</tr>
</thead>
</table>
</div>
</div>
複製代碼
<div class="table-body" @scroll="tableScroll" style="height: 300px">
<div class="module"
style="width:3000px;"
v-for="(item, index) in monthData" v-bind:key="index">
<div class="content"
v-if="Math.abs(index - curModule) < 3">
<div class="row"
style="height:30px"
v-for="(p_item, p_index) in projectData"
v-bind:key="p_index">
<table width="3000"
v-if="Math.abs(p_index - curRow) < 20"
cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td
@click="clickTd(p_index,item.month, d_item, $event)"
v-for="(d_item, d_index) in item.days" v-bind:key="d_index">
<span v-if="!originProjectData[p_index][''+item.month][''+d_item]['show']">{{originProjectData[p_index][''+item.month][''+d_item]['last']}}</span>
<input
@blur="blurTd(p_index,item.month, d_item)"
v-if="originProjectData[p_index][''+item.month][''+d_item]['show']"
v-model="originProjectData[p_index][''+item.month][''+d_item]['last']"
v-focus="originProjectData[p_index][''+item.month][''+d_item]['focus']"/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
複製代碼
通過如上優化,完美解決表格卡頓問題,可是我並無封裝組件,緣由以下
·插件封裝後會有不少限制,不能再用vue那種模板寫法,用json傳入數據,自定義內容不是很靈活
·能夠根據本身的應用場景自行修改拓展,代碼已經很簡潔
·比較懶
複製代碼