近几个月在开发一个基于Vue的数据可视化分析辅助应用———DMap(谛听),一套为数据分析师和数据科学家提供的基于位置大数据分析的工具,旨在提高数据分析效率,降低获取多数据并行分析成本,简化大屏和数据报告开发制作流程。UI组件使用的是iView,地图可视化库使用的是inMap,服务端使用Node.js搭建。

DMap的核心就是服务大数据分析,所以当面对几万几十万甚至百万级别的数据时,性能优化是一个具有挑战性的问题。今天我就拿项目中一个表格渲染的优化为例来展开介绍。

在前端开发中,用表格来展示数据是再平常不过的了,当数据量较多时,我们通常的做法是使用分页,如果数据量不算太多只有两三页,我们大可以把全量数据获取下来,在前端做简单的分页展示。当数据量再上一个等级时,我们就需要根据页数向服务端请求这一页需要的数据。但是DMap作为助力大数据可视化的分析工具,我们需要将全量的数据在前端做展示,而为了提升用户体验,我们在表格的展示上决定不做分页,也不做懒加载,而是像Excel那样可以无缝隙的滚动。

在Web中,长列表渲染的性能问题已经有一些成熟的方案,表格和长列表相似,当渲染的行数达到一定量时,滚动就会变得卡顿,所以我们使用了虚拟渲染的方案,就是只渲染用户所能看到的区域的一小部分数据,然后通过滚动来计算显示的数据,和上下占位元素的高度。

通过这个图可以对原理有个大概的了解,接下来说下计算上的细节。

首先我们需要监听表格外层容器(也就是显示滚动条的元素)的scroll事件,在scroll事件绑定的方法中我们只做一件事,那就是获取外层容器当前滚动了的高度scrollTop的值。我们的所有计算,包括三个表格位置的替换、表格数据的选取、上下占位元素的高度的计算都与scrollTop相关。

下面是scroll事件的绑定的方法:

    handleScroll (e) {const ele = e.srcElement || e.target;const { scrollTop, scrollLeft } = ele;this.scrollLeft = scrollLeft;this.scrollTop = scrollTop;}
复制代码

我们只需要在这里把scrollTop和scrollLeft的值赋给vue实例对应的值,然后我们用watch监听scrollTop的改变,如果更新了,就来计算当前处于可视区域的表格索引号currentIndex:

this.currentIndex = parseInt((top % (this.moduleHeight * 3)) / this.moduleHeight);
复制代码

这的top就是更新后的this.scrollTop的值,moduleHeight是单个表格的高度,我们称它为一个模块。

拿到currentIndex的值后,我们就可以计算三个表格的显示位置,和每个表格中填充的数据。三个表格我们是通过render函数渲染的,我们根据currentIndex的值来返回不同顺序的render函数:

getTables (h) {let table1 = this.getItemTable(h, this.table1Data, 1);let table2 = this.getItemTable(h, this.table2Data, 2);let table3 = this.getItemTable(h, this.table3Data, 3);if (this.currentIndex === 0) return [table1, table2, table3];else if (this.currentIndex === 1) return [table2, table3, table1];else return [table3, table1, table2];
}
复制代码

数组中表格顺序不同,反应在页面上的效果就是不同的先后顺序。最后我们通过这个方法得到完整的render:

 renderTable (h) {return h('div', {style: this.tableWidthStyles}, this.getTables(h));}
复制代码

然后使用封装的无状态的组件,来渲染我们得到的表格render。

<render-dom :render="renderTable"></render-dom>
复制代码

renderDom组件的实现如下:

export default {name: 'RenderCell',functional: true,props: {render: Function,backValue: [Number, Object]},render: (h, ctx) => {return ctx.props.render(h, ctx.props.backValue, ctx.parent);}
};
复制代码

接下来我们讲下三个表格中填充的数据的计算。

我们按照三个模块都在可视区域经过一次算是一轮,通过scrollTop来和currentIndex来计算每个模块当前是在第几轮展示,但因为我们是从第二个表格才开始做这个逻辑的处理(为了轮播效果更平滑),所以要先判断当前滚动的高度是否大于一个模块的高度,如果大于才做如下计算:

switch (this.currentIndex) {case 0: t0 = parseInt(scrollTop / (this.moduleHeight * 3)); t1 = t2 = t0; break;case 1: t1 = parseInt((scrollTop - this.moduleHeight) / (this.moduleHeight * 3)); t0 = t1 + 1; t2 = t1; break;case 2: t2 = parseInt((scrollTop - this.moduleHeight * 2) / (this.moduleHeight * 3)); t0 = t1 = t2 + 1;
}
复制代码

计算出每个模块在第几轮展示后,就可以来取对应的表格数据了:

const count1 = this.times0 * this.itemNum * 3;
this.table1Data = this.insideTableData.slice(count1, count1 + this.itemNum);
const count2 = this.times1 * this.itemNum * 3;
this.table2Data = this.insideTableData.slice(count2 + this.itemNum, count2 + this.itemNum * 2);
const count3 = this.times2 * this.itemNum * 3;
this.table3Data = this.insideTableData.slice(count3 + this.itemNum * 2, count3 + this.itemNum * 3);
复制代码

到这里虚拟渲染的重要内容都介绍完了。表格开发完成后,在项目中实际使用时,当加载二十多万条数据来测试时,整个页面卡的让人无法忍受,数据量越大页面卡顿越严重。我们的表格是没有问题的,问题出在Vue帮了我们“倒忙”。

在Vue实例中添加的对象,Vue会先遍历一遍对象的所有属性,用Object.defineProperty()为每个对象创建对应的getter和setter。而在项目中,我们的insideTableData只是一个数据集对象中的一个属性,这个对象还包括很多与这一个数据集相关的信息,我们在使用this.insideTableData.slice获取数据的时候会触发this.insideTableData对应的getter,从而执行一些其他逻辑,而我们的滚动又会频繁的(仅当currentIndex变化的时候)需要重新填充表格数据,所以这会造成卡顿。

解决这个问题的办法就是阻止Vue给我们的数据集对象设置对应的setter和getter,我的方法就是使用ES5的Object.preventExtensions在将数据集对象交给Vue实例代理前将对象密封,这样数据集对象就变成了不可拓展的了,Vue就不会再添加新的属性了,也就无法设置setter和getter了。

做了这个处理后渲染几十万数据跟玩儿似的流畅。但是阻止Vue设置getter和setter也造成了一些问题,比如原来表格组件中的一些依赖于表格数据的计算属性,现在无法在表格数据变化时重新计算,当然了,影响不大,就一个表格行数的计算,所以改成了手动设置这个值。

到这里要讲的差不多了,这只是项目中的一点优化内容,我封装的vue-bigdata-table(没办法,好名字都被注册了)表格组件不仅仅这点功能,目前还包括拖动修改列宽、固定列不横向滚动,固定表头、内置排序、编辑单元格、粘贴、筛选、自定义表头和单元格等功能。现在也已经开源了,但是还有很多功能还在开发中。

想玩儿转Vue技术栈开发,从创建项目开始,到项目部署上线,可以看我的最新视频教程:《Vue技术栈开发实战》。

Github链接:github.com/lison16/vue…

欢迎Star。

DMap(谛听)——实战Vue百万条数据渲染表格组件开发相关推荐

  1. vue 大数据 渲染_技术专栏 | DMap——实战Vue百万条数据渲染表格组件开发

    作者:TalkingData 李志刚 本文由TalkingData原创,转载请获取授权. 李志刚:近几个月在开发一个基于Vue的数据可视化分析辅助应用---DMap(谛听),一套为数据分析师和数据科学 ...

  2. 支持大数据渲染下拉列表组件开发 SuperSelect(基于antd Select)

    功能简介 antd 的 Select 组件不支持大数据量的下拉列表渲染,下拉列表数量太多会出现性能问题, SuperSelect 基于 antd 封装实现,替换原组件下拉列表,只渲染几十条列表数据,随 ...

  3. JAVA导出exls时报oom_如何实现导出百万条数据到EXCEL中不报OOM异常?

    Java项目中使用POI导出百万条数据到Excel中,但是会出现内存溢出异常. 存在以下问题需要考虑POI导出条数限制6w+ 数据量大的话会导致内存溢出 现在的做法是每6w条数据做一次分割,创建一个新 ...

  4. 如何给mysql表添加百万条数据_给mysql一百万条数据的表添加索引

    直接alter table add index 添加索引,执行一个小时没反应,并且会导致锁表:故放弃该办法,最终解决办法如下: 一.打开mysql 命令行客户端 这里我们那可以看到导出的数据文件所存放 ...

  5. java读取百万条记录出错_如何实现导出百万条数据到EXCEL中不报OOM异常?

    Java项目中使用POI导出百万条数据到Excel中,但是会出现内存溢出异常. 存在以下问题需要考虑POI导出条数限制6w+ 数据量大的话会导致内存溢出 现在的做法是每6w条数据做一次分割,创建一个新 ...

  6. 解决Ionic的ion-slide-box 2条数据渲染问题

    解决Ionic的ion-slide-box 2条数据渲染问题 参考文章: (1)解决Ionic的ion-slide-box 2条数据渲染问题 (2)https://www.cnblogs.com/ye ...

  7. 【SpringBoot项目中使用Mybatis批量插入百万条数据】

    SpringBoot项目中使用Mybatis批量插入百万条数据 话不多说,直接上代码,测试原生批处理的效率 开始测试 背景:因为一些业务问题,需要做多数据源,多库批量查询.插入操作,所以就研究了一下. ...

  8. jdbc批量插入的4种方式【百万条数据插入只需几秒】

    mysql数据库准备 #打开数据库test01; use test01; #创建表a,表a包含int型的id列.可变长度型的name[长度20个字符] create table a (id INT,N ...

  9. ThinkPHP导出百万条数据量

    项目中,需要将数据库中的百万条数据导出,用PHPExcel的话,PHP内存会各种溢出什么的,所以就用的CSV批量导出再打包下载,随后删除生成的数据. public function excelout( ...

最新文章

  1. html页面转换成pdf
  2. PaddleHub 1.0正式发布: 一键模型加载,十行代码完成迁移学习
  3. 2020华为推迟发布鸿蒙战略,早新闻:华为5nm麒麟芯片延期,确认新版鸿蒙将发...
  4. 关于通过使用BAPI创建销售订单(抬头信息中:含增强字段)
  5. pytorch 常用层(四)
  6. 架构师讲解Java中websocket的应用
  7. [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并
  8. TIM SWEENEY:引擎及图形学的未来
  9. flashfxpFTP链接显示PASV、列表错误
  10. [USB 设备检测_1]-使用 H2testw 1.4 或其她工具检测新买的朗科 U 盘读写速度及是否是扩容盘
  11. android 国家代码
  12. 精读《图解密码技术》--第一章 环游密码世界
  13. Docker容器引擎
  14. 前端面试宝典 html css js ajax es6
  15. 【大学课程自学网站】
  16. 函数节流(Throttle)和防抖(Debounce)解析及其OC实现
  17. 统计学习导论(ISLR)(四):分类算法
  18. 标题 穿越雷区 java_6届国赛java试题 4: 穿越雷区
  19. Mac 自带拼音输入法技巧
  20. 【图像处理】——Python+opencv实现图像的hu不变矩特征提取(含原理、推导过程、应用、代码等)

热门文章

  1. 搭建 rasa 框架中遇到的 domain.yml 无效问题
  2. 上海2013年驾校科目二学习心得,完全是我自己总结的。
  3. wxwork和wx.qy判断企业微信小程序编译运行环境
  4. 刨根问底:Windows CTF协议安全性研究
  5. 【周志华机器学习】六、支持向量机
  6. 去哪儿旅行携程旅行淘宝旅行移动端产品分析报告
  7. 视频剪辑使用的素材得怎么找?
  8. 玩电脑玩出的 Linux 专家 - Google(谷歌)开发者日演讲者之苏哲
  9. 单词拆分java与填表法_139. 单词拆分
  10. 计算机等级ps考试1试题,计算机等级考试一级PS考前试题及答案一