资讯专栏INFORMATION COLUMN

vueTable大数据展示优化

JasinYip / 2387人阅读

摘要:懒加载方式常见的有淘宝一屏用元素占据一定的高度,然后再去拉图片数据。但这种方式还是需要元素占位,淘宝一页的数据量其实不算大,因为它结合了分页。

背景


大数据项目根据用户输入代码查询数据,用户的代码不可控(比如select from db limit 5000),有可能一页需求要求展示100行5000列数据。由于是用户代码实时查询的数据,后端不可能将所有查询结果都存储。因此,查询的结果是实时的、全量的,分页和排序都需要前端去实现

现状

刚开始的接手项目的时候完全不能展示十万级的数量,chrome标签页直接崩溃。这个在分析了需求,展示数据不需要响应式后,用了Object.freeze()后就可以勉强展示十万级数据。虽然还是卡顿,但是需求已经实现。(值得注意的是Object.freeze()并不是深度冻结,实际应用中对象要进行递归操作。)

下面图展示的是100行乘以一千列,在左右拖拽0-150列。目前也对超过两百列的数据进行横向的懒加载操作,实现原理时监听scroll事件滚动到末尾时截取对应下一组数据,然后将滚动条恢复到头部。可以从gif中明显感觉到这个过程是滚动条恢复到原状之间耗时比较长。而且当用户想要看前一组数据的最后一项和后一组数据的前一项时,js就要不停地做截取数据的操作重新渲染,开销非常大。

利用chrome devtool performance进行性能分析。(进行性能分析时使用隐身模式避免chrome插件对结果分析造成偏差)

观察FPS图表,有几段红帧证明这过程中页面超负荷,会出现卡顿响应缓慢等。

选中红帧区域,Main区域发生变化,变为当前选择时段的函数调用栈详情。点击会在下面的Summary里发现对应的信息以及警告提示回流可能为性能的瓶颈Forced reflow is a likely performance bottleneck.。对应的问题出在监听scroll事件后出现的js代码中,执行的次数非常多。不仅需要去读取scrollLeft值,还因为重新渲染数据时使组件纵向高度发生了改变,进而多次触发了element-ui组件的updateScrollY方法。从Screenshots可以看到这时刚好是数据移动到最后要对数据进行截取重新渲染。

从上图summary可以看到js的运行压力很大,勾选memory项纪录js heap占用情况,查看到占用高达161mb-325mb

优化要点

table的数据并不会有修改的需要,仅仅是展示,并不需要响应式。Object.freeze()可以阻止vue追踪属性的变化,减少性能的开销

由于数据展示的table不仅大量而且经常变换数据集。为了减少回流和重绘,table做绝对定位脱离文档流,避免布局抖动。

由于后端返回的数据一组表头和内容分开的数组,而开源element-ui的vue组件都是以key:value的形式,大量数据情况下仅仅是将数组转化为key:value的形式就花费掉几百毫秒的时间。开源组件能解决的是通用情况,这种情况下为了尽量减少开销重写适用于业务的table组件还是很有必要的。

//后端返回的格式
data = [
    columnName: ["col1", "col2", ……],
    columns: [
        ["1", "2", ……],
        ["1", "2", ……],
        ……
    ]
]
// 开源组件需要的格式
data = [
    {
        col1: "1",
        col2: "2",
        ……
    },
    {
        col1: "1",
        col2: "2",
        ……
    }
]

后端返回的数据量有可能高达百万级,尽管前端进行分页还是有可能要展示到数量达十万。其中行最多每页只展示100条,但是列由ide用户执行的代码决定,这里主要影响性能的是列数。列数有可能为1000条,模拟横向懒加载,将拿回来的数组截取部分展示,减少页面上的dom节点。但是目前模拟懒加载的方式用户体验不好。

为了解决横向滚动时相邻列的数据能够展示在同一屏上,而不需多次来回切换,首先做的工作是在截取数据时保留前一屏的数据,拖动后滚动条回到中间位置,在一定范围内不需要多次滚动才能查看。(如下图)

- 但这种方式也是非常不友好,每次滚动到最后要去检测用户是否按着鼠标有没有抬起,防止触发多次数据重新渲染。因为这种情况下,用户拖一次只能加载一组新数据,滚动条便回到了中间位置,如果用户需要看到最后一组数据就要多次操作。正常的懒加载应该是有一条适应高度的滚动条拖拽,无缝连接。

- 懒加载方式常见的有:
    1. 淘宝一屏用元素占据一定的高度,然后再去拉图片数据。滚动条便适应高度的拖动距离。但这种方式还是需要元素占位,淘宝一页的数据量其实不算大,因为它结合了分页。
    2. 掘金沸点的无限加载:掘金的方式是监听到底部时,再去拉响应的数据追加,滚动条会自适应滚到相对应的地方。但是掘金这种懒加载一直加载数据没有截取掉旧数据,所以滚动条距离也是一直适应数据的。尝试将掘金沸点一直拖动到2000条,网页已经开始有点卡顿。而在ide项目中,两千条数据算是少量数据。
- 启发于[https://github.com/tangbc/vue-virtual-scroll-list](vue-virtual-scroll-list),利用了padding值模拟了淘宝固定高度,不需要元素占位,模拟出全部数据量的滚动条纵向滚动距离,拖动时完全无感知数据的重新渲染。目前vue-virtual-scroll-list只支持纵向,但稍微改造下就能用在ide项目的横向懒加载。(改造后如下图,gif软件录制时稍微有点卡顿感)

scroll长时间运行的重新计算样式事件,其时间如果超过 16.7 毫秒,并且恰好发生在滚动期间,导致用户体验到明显的抖动。为了在拖动过程中数据变化以连贯、平滑进行过渡,函数节流改setTimeout为requestAnimationFrame(rAF),由系统来决定回调函数的执行时机;它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致渲染数据出现卡顿的问题,并且rAF能兼容到ie9以上了。

优化后结果分析

拖动几百条数据截取的performance在FPS图表中已经没有最初的红标,没有Forced reflow,每帧的rendering也由rAF控制在16.7ms以内,js内存占用也从161mb-325mb,降低到157mb-196mb。

组件接口设计原则

复用性:配置参数的方式去差异化体现,参数的可配置性提高了组件的复用率和灵活性。
可维护性:组件化后,组件内部的逻辑只对组件负责,外部的逻辑只通过配置参数适配,提高了代码的逻辑清晰度,可以快速定位代码出现问题的地方。

这个组件设计时对外提供toLefttoRightonScroll事件,分别是滑动过程中到了头、尾,及滑动过程的回调。提供了offsetremainbench参数表示刚渲染时的偏差,显示的列数,及保留多少列在实际dom中。

小结

以前没有想过js也会承受那么大的压力,一点点优化都能显著减轻内存。在写代码时要特别关注高频事件的触发,一切的优化方向就是在实现功能的前提下减少重新渲染的发生。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98196.html

相关文章

  • 推荐给新手的35个好用的Vue开源库

    摘要:无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包。所幸的是,随着社区的不断壮大,每天都会出现一些很好的软件包。在下文中,我们将推荐一些非常好用的开源库是一个非常易用的渐进式框架,用于构建用户界面。的一个极简主义的深色设计系统。 无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包。对于开发者来说,如果没有这些开源软件包,很难想象我们的生活会变得多么疲惫不堪,而且靠咖啡度日也会成...

    oliverhuang 评论0 收藏0
  • 一个通用的vue的表格组件

    摘要:在做业务组件的时候需要自己自己封装一个通用的表格,这个表格需要符合我们一切的好的幻想,左右固定,表头固定,分页,选择,一直表格内容的行数限制等等,下面就为大家介绍一下这一款表格组件功能以及怎么使用。 在做业务组件的时候需要自己自己封装一个通用的表格,这个表格需要符合我们一切的好的幻想,左右固定,表头固定,分页,选择,一直表格内容的行数限制等等,下面就为大家介绍一下这一款表格组件功能以及...

    caoym 评论0 收藏0
  • 一个通用的vue的表格组件

    摘要:在做业务组件的时候需要自己自己封装一个通用的表格,这个表格需要符合我们一切的好的幻想,左右固定,表头固定,分页,选择,一直表格内容的行数限制等等,下面就为大家介绍一下这一款表格组件功能以及怎么使用。 在做业务组件的时候需要自己自己封装一个通用的表格,这个表格需要符合我们一切的好的幻想,左右固定,表头固定,分页,选择,一直表格内容的行数限制等等,下面就为大家介绍一下这一款表格组件功能以及...

    bingo 评论0 收藏0
  • Vue前端开发规范

    摘要:正例复制代码反例复制代码组件数据组件的必须是一个函数。正例更好的做法复制代码反例这样做只有开发原型系统时可以接受复制代码为设置键值总是用配合。这条规则只和单文件组件有关。基于Vue官方风格指南整理一、强制1. 组件名为多个单词组件名应该始终是多个单词的,根组件 App 除外。正例:exportdefault{name:TodoItem,//...}复制代码反例:exportdefault{n...

    番茄西红柿 评论0 收藏2637
  • 使用Performance对页面进行分析优化(实战篇)

    摘要:在此,我们可以使用懒加载方式对其进行优化,仅展示其对应类型的图,避免了不必要的资源浪费和计算时间。 这篇文章将介绍下实际使用performance对页面进行优化的过程。总的来说,chrome performance工具让我们更方便的发现在代码运行过程中的问题在哪里,便于对一些可能注意不到的问题进行定位、分析和优化。原文首发于个人博客 渲染优化 首先,我们对进入整个详情页进行分析,整个页...

    luodongseu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<