背景
前段时间接手了别人的甘特图代码,领导要求把甘特图封装成公共组件,心里想着这不是很简单的事情,封装之后功能正常,测试通过,上线,搞定,万事大吉。
但不幸的事情还是发生了:有客户说甘特图页面打不开,分析了一下原因,看了接口,没返回数据得嘛,后端原因,甩锅。
但是后来仔细分析,根本原因是数据量太大,页面渲染的时候导致浏览器卡死,所以也看不到接口返回的数据了。好嘛,锅又回来了。
解决方案
1. canvas 画图
2. 虚拟滚动
画图太慢,且不是很熟练,最终选择虚拟滚动。
难点
常见的虚拟滚动都是列表,且要么横向滚动,要么纵向滚动,这里同时包括:
1. 横向纵向都要虚拟滚动
2. 纵向是数据结构是树形结构
3. 横向是日期,切换到周视图或月视图时,每个格子的宽度不一致
4. 图上还有进度条,以前的实现逻辑是悬浮在背景上的,也要做处理
实现细节
纵向虚拟滚动
找了大佬现成的代码直接套,hhhhh
大体思路就是把拿到的树状结构数据铺平,问题转化为列表的处理方式
横向虚拟滚动
这个需求很少见,找不到现成的,只能自己从头撸。
分析:
一般的虚拟滚动依据滚动距离来计算,这里由于是日期,每周每月的宽度不一样,所以只能依据滚动的格子数来计算。
将日期转换为宽度数据来处理。
由于vue的渲染方式是只重新渲染数据变化的那一部分,所以我只需要关心每次滚动之后要渲染哪些数据就行,有重合的数据底层diff算法能够识别到(这里体现出v-for是设置key的重要性)。
进度条处理
如果单独处理,实现起来比较繁琐,要考虑进度条长度,开始位置,结束位置。索性把进度条放到每个格子里,这样处理格子渲染的时候顺便就把进度条一起带上了。
好家伙,说起来简单,实际花了我大半天时间(改别人的代码,懂得都懂):
1. 进度条大于格子宽度时,分为开始格子,中间格子,结尾格子,开始和结尾要根据时间计算宽度占背景格子百分百,中间格子必定撑满背景格子
2. 进度条小于格子宽度时,根据开始结束时间计算占了背景多少百分比,并计算左右边距
3. 以上两条,日视图,周试图,月视图计算逻辑都有所区别,要分别计算,这里就不展开讲了
后悔,还不如直接处理进度条虚拟滚动
总结:
1. 充分利用vue数据驱动视图原理
2. 写代码之前要想清楚了再干,并且尽可能的想到每一处的细节,不然写到一半才发现有问题来不及了,自己选的路,跪着也要走完。