1. 问题描述
由于业务需求,需要在一个页面中点击查询按钮时加载出所有的数据,但数据量有近10万条,渲染出现卡顿,页面卡死。
2. 常见的解决方案
- 自定义中间层
自定义nodejs中间层,获取并拆分这10w条数据,
前端对接nodejs中间层,而不是服务器
缺点:成本高
- 虚拟列表
只渲染可视区域DOM,其他隐藏区域不显示,只用div撑起高度,随着浏览器滚动,创建和销毁DOM。
虚拟列表实现起来非常复杂,可借用第三方lib
Vue-virtual-scroll-list
React-virtualiszed
- 前后端配合(本问题解决方案)
前端使用pl-table加载数据;pl-table(大数据表格,完美解决万级数据渲染卡顿问题)
后端循环获取数据,每次只获取几百条数据,获取后就进行渲染。
3. 解决方案流程图
使用pl-table + 每次从后端读取500条数据后就渲染 ,渲染完成后如果还有数据继续获取数据500条并渲染,直至数据读取完成。
流程图如下图所示:
1)点击查询按钮
2)判断是否正在查询(isSearching)
3)isSearching = true ;正在查询时判断是否需要停止,需要停止则查询结束;不需要停止则继续查询过程(不需要额外操作)。
4)isSearching = false ;没有正在查询,这时需要设置 isSearching = true;startId = 0 (查询的开始id);
searchingTaskTag = genUuid()// 随机数(用来在前后端传递,保证是同一个查询)
5)调用中间fn1函数,判断当前请求数据的最大Id是否小于等于0,如果小于等于0 则请求出最大maxId,并设置endId = startId + step(查询的结束Id);
6) 判断startId <= maxId 为true,则调用函数fn2,随机数searchingTaskTag请求和响应中携带。
7)根据response.searchingTaskTag === searchingTaskTag 判断是否是同一个请求,如果是数据则累加进去,同时 startId = startId + step;并去调用步骤5)。
8)判断startId <= maxId 为false,则结束查询。
4. 代码
查询方法
//查询 handleSearch() { //this.isShow = false; if (this.isSearching) { // 提示用户是否停止查询? this.$confirm("确认停止查询?", "提示", { 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(); } },
中间函数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("查询结束!"); this.isSearching = false; } } catch (e) {} }, getMaxId() { getMaxId() .then((resp) => { this.maxId = resp.body; }) .catch((error) => { this.$message.error(error.body); }); },
fn2 函数
//获取数据列表 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; },
到此这篇关于vue渲染大量数据时卡顿卡死解决方法的文章就介绍到这了,更多相关vue渲染数据内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!