vue渲染大量數(shù)據(jù)時(shí)卡頓卡死解決方法
1. 問題描述
由于業(yè)務(wù)需求,需要在一個(gè)頁面中點(diǎn)擊查詢按鈕時(shí)加載出所有的數(shù)據(jù),但數(shù)據(jù)量有近10萬條,渲染出現(xiàn)卡頓,頁面卡死。
2. 常見的解決方案
- 自定義中間層
自定義nodejs中間層,獲取并拆分這10w條數(shù)據(jù),
前端對接nodejs中間層,而不是服務(wù)器
缺點(diǎn):成本高
- 虛擬列表
只渲染可視區(qū)域DOM,其他隱藏區(qū)域不顯示,只用div撐起高度,隨著瀏覽器滾動(dòng),創(chuàng)建和銷毀DOM。
虛擬列表實(shí)現(xiàn)起來非常復(fù)雜,可借用第三方lib
Vue-virtual-scroll-list
React-virtualiszed
- 前后端配合(本問題解決方案)
前端使用pl-table加載數(shù)據(jù);pl-table(大數(shù)據(jù)表格,完美解決萬級數(shù)據(jù)渲染卡頓問題)
后端循環(huán)獲取數(shù)據(jù),每次只獲取幾百條數(shù)據(jù),獲取后就進(jìn)行渲染。
3. 解決方案流程圖
使用pl-table + 每次從后端讀取500條數(shù)據(jù)后就渲染 ,渲染完成后如果還有數(shù)據(jù)繼續(xù)獲取數(shù)據(jù)500條并渲染,直至數(shù)據(jù)讀取完成。
流程圖如下圖所示:
1)點(diǎn)擊查詢按鈕
2)判斷是否正在查詢(isSearching)
3)isSearching = true ;正在查詢時(shí)判斷是否需要停止,需要停止則查詢結(jié)束;不需要停止則繼續(xù)查詢過程(不需要額外操作)。
4)isSearching = false ;沒有正在查詢,這時(shí)需要設(shè)置 isSearching = true;startId = 0 (查詢的開始id);
searchingTaskTag = genUuid()// 隨機(jī)數(shù)(用來在前后端傳遞,保證是同一個(gè)查詢)
5)調(diào)用中間fn1函數(shù),判斷當(dāng)前請求數(shù)據(jù)的最大Id是否小于等于0,如果小于等于0 則請求出最大maxId,并設(shè)置endId = startId + step(查詢的結(jié)束Id);
6) 判斷startId <= maxId 為true,則調(diào)用函數(shù)fn2,隨機(jī)數(shù)searchingTaskTag請求和響應(yīng)中攜帶。
7)根據(jù)response.searchingTaskTag === searchingTaskTag 判斷是否是同一個(gè)請求,如果是數(shù)據(jù)則累加進(jìn)去,同時(shí) startId = startId + step;并去調(diào)用步驟5)。
8)判斷startId <= maxId 為false,則結(jié)束查詢。
4. 代碼
查詢方法
//查詢 handleSearch() { //this.isShow = false; if (this.isSearching) { // 提示用戶是否停止查詢? this.$confirm("確認(rèn)停止查詢?", "提示", { type: "warning", }).then(() => { this.listLoading = false; this.searchingTaskTag = ""; this.isSearching = false; this.hardReset = false; this.$nextTick(() => { this.hardReset = true; }); }); } else { this.isSearching = true; this.searchingTaskTag = genUuid(); this.tableData = []; this.startId = 0; this.fn1(); } },
中間函數(shù)fn1
async fn1() { let startId = this.startId; let endId = this.startId + this.step; let param = { pageNo: this.page, pageSize: this.pageSize, startId: startId, endId: endId, searchingTaskTag: this.searchingTaskTag, }; try { if (this.maxId <= 0) { let response = await getMaxId(); this.maxId = response.body; } if (startId <= this.maxId) { this.fn2(param); } else { this.$message.success("查詢結(jié)束!"); this.isSearching = false; } } catch (e) {} }, getMaxId() { getMaxId() .then((resp) => { this.maxId = resp.body; }) .catch((error) => { this.$message.error(error.body); }); },
fn2 函數(shù)
//獲取數(shù)據(jù)列表 fn2(param) { fn2(param).then( (resp) => { let tempList = resp.body.content; let echoSearchingTaskTag = resp.body.searchingTaskTag; if ( tempList.length > 0 && this.searchingTaskTag == echoSearchingTaskTag ) { this.tableData.push(...tempList); } if (this.searchingTaskTag == echoSearchingTaskTag) { this.listLoading = false; this.startId += this.step; this.fn1(); } }) .catch((error) => { this.listLoading = false; this.$message.error("獲取失?。?); this.isSearching = false; this.flag = false; }); this.listLoading = false; },
到此這篇關(guān)于vue渲染大量數(shù)據(jù)時(shí)卡頓卡死解決方法的文章就介紹到這了,更多相關(guān)vue渲染數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)簡易計(jì)算器
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)簡易計(jì)算器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02js代碼實(shí)現(xiàn)點(diǎn)擊按鈕出現(xiàn)60秒倒計(jì)時(shí)
這篇文章主要為大家詳細(xì)介紹了js代碼實(shí)現(xiàn)點(diǎn)擊按鈕出現(xiàn)60秒倒計(jì)時(shí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-12-12js實(shí)現(xiàn)從右向左緩緩浮出網(wǎng)頁浮動(dòng)層廣告的方法
這篇文章主要介紹了js實(shí)現(xiàn)從右向左緩緩浮出網(wǎng)頁浮動(dòng)層廣告的方法,可實(shí)現(xiàn)右側(cè)浮動(dòng)廣告的定時(shí)彈出及點(diǎn)擊展開、折疊等功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05JavaScript是如何實(shí)現(xiàn)繼承的(六種方式)
大多OO語言都支持兩種繼承方式: 接口繼承和實(shí)現(xiàn)繼承 ,而ECMAScript中無法實(shí)現(xiàn)接口繼承,ECMAScript只支持實(shí)現(xiàn)繼承,而且其實(shí)現(xiàn)繼承主要是依靠原型鏈來實(shí)現(xiàn),下文給大家技術(shù)js實(shí)現(xiàn)繼承的六種方式,需要的朋友參考下2016-03-03JavaScript switch case 的用法實(shí)例[范圍]
JavaScript switch case 的用法實(shí)例,大家可以參考下。2009-09-09js和jquery中循環(huán)的退出和繼續(xù)下一個(gè)循環(huán)
退出循環(huán),使用break;退出當(dāng)前循環(huán)繼續(xù)下一個(gè)循環(huán),使用continue,jquery中使用return false;continue,使用return true2014-09-09