之所以特别是因为以往面试问到这种问题,我都会提一嘴虚拟滚动,然而这次尝试了此方案却不行,最终用了 Vant4 内置的 lazy-component 组件,写完此篇就去看一下源码。
先说下背景,这一块的逻辑我之前是没参与的,测试跟我说卡我就让他找这个模块的负责人了,简称小张吧,隔了一段时间产品也说卡,我也没太在意,我这边也很忙,我还是让小张看了,我看他和后端讨论挺多的,他没解决他也没问我,我以为早就没事了。
直到最后项目组长直接找到了我,说这个拖太久了,客户反馈没法做事,让我这个版本解决掉,此时留给我的时间已经不多了。在我的印象中,前端是很难有什么性能的问题,有也就是搞出什么死循环了,仔细检查下代码就行了,更多的是后端的接口返回问题。
移动端项目,当时给我演示时,有一个楼有五千多的房屋,万科云城,我还在附近上过班,这是真是存在的,其实是好几栋楼,但是只有一个房屋编码,所以划分到了一起。
十多分钟也渲染不出来,产品有录屏,我也是很震惊,我真没想到会这么卡,这几乎就是卡死了。
业务功能是先分楼栋,楼栋下面是房屋,然后按照楼层来渲染房屋,左侧是楼层,右侧是房屋,要求可以一直向上滑动,自动切换楼层,点击楼层也可以跳转到对应房屋。
但是五千条数据也不多,因为我有 sf-mock,在测试环境 copy 了一个有八百多房屋的接口数据,我在接口对应 mock 数据的 JS 文件中,通过 Array 方法搞到了五千,在电脑上挺快的,直到搞到一万,才特别的卡。
我看了下实现,一开始处理数据确实有很多排序,可通过 console 函数发现用时不到一秒。也就是问题出现在模板渲染上,可这里面只有一个双重循环,用双重确实没必要,他大概率是为了实现定位,就是从结构上多了一个楼层的 div ,里面是三个折叠展开,有一个循环渲染标签。
我也没多想,就想着直接用虚拟滚动算了,一搜方案很多,但是用起来却没啥效果,好不容易折腾出一个能用的,渲染确实块,这种方案其实已经不在乎你有多少数据了,因为它一次只渲染十几个。但是问题来了,每个房屋块的高度是不一样的,这个组件一开始要设置一个最小高度,这就导致不同房屋块的间距不一样,而且房屋块里有操作是可以改变自身高度的,这就导致了上下两个房屋块会发生重叠,虽然文档上有说可以适配动态高度的方法,但是我尝试了没用。
最重要的一点,我看我尝试过的虚拟滚动方案,都是基于 translateY 来实现的,我理解点击折叠展开这种是可以通过事件来触发的,这样我就可以把已经渲染的房屋快的位置计算一遍,我甚至可以自己监听,那么问题来了,当我滑动的时候,会出现已经渲染过的房屋块不渲染了,是不是就意味着状态无法保留?而且定位这种也没法实现。
所以虚拟滚动这种方案就是行不通的,这块也应该再从方案和源码两个维度研究下,如果真的是上述这种,那么我觉得虚拟滚动有点鸡肋。
我得知这个结论后已经独自加班到 11 点没搞成功虚拟滚动,再搭上一个早晨搞成了却发现没用,时间只剩下一天半了,明天就发版了,我们很疯狂,周一过需求,周四发版,所以很多功能周四上午提测很正常,还有更疯狂的,就不多说了。
我又仔细看了下代码,这些关键性代码其实是上一个人写的,这个人已经离职了,他当时跟我讨论方案,我就提议后端接口先返回一个不同楼层对应的房屋数信息,然后接口支持传递楼层返回房屋信息,支持传递多个楼层,完成初始化加载后就可以根据用户操作进行预加载了,然而他最后告诉我他一次性加载了全部。当然现在看这个方案,在实现上是有很多细节要去处理的,想要做的好是要花很多时间的。
我又仔细看了下代码,用了挺多没必要的计算属性,冗余代码太多了,而且这些计算属性用在很多业务代码中,可说实话,我没有把握重写一遍能解决掉卡顿的问题,最关键的是,我没把握不改出新的问题,里面挺多细小的点。
这时候我有了一个最稳妥的方案,那就是尽量不改动逻辑和结构,那就是超过一定房屋的话,比如 600,自动把楼栋分组,其实这也很合理,首先生产的数据很少有超过一千的,一千也就七八秒,最常见的也就是四五百,也就是需要分组的不多。
从用户使用角度来讲,我觉得网格员不管干啥任务,从第一个房屋一个个看完五千个是不可能,所以从上面加个分组也好,因为左侧多了也是会出现滚动条,不好定位的,当然尽量少出现分组,因为水平滚动也不好。
我甚至觉得这个东西从设计产品的时候就应该考虑了,打电话和产品沟通了一波,她的意见不大,我就把这个方法跟小张说了,让他先写着,按照 500 来试试。
我开始注释 HTML 代码,先单一变量法再组合,发现不使用 van-text-ellipsis 区别很大,尤其代码里用了多个。
确实可以自己用 css ,那么换一个思路,如果只是视口内的组件才展示全部的信息呢,这时候同事已经完整分组逻辑,我用真机体验了一下,还是比较慢。
于是我就使用了 lazy-component,确实有明显提升,我将分组改到 800,大概两三秒的样子,其实一开始也有尝试,只不过当时数据太多,感觉不明显。整体改动正好当天完成。
虚拟滚动、van-text-ellipsis、lazy-component 这下有时间研究下了,因为不同意降薪被裁掉了,说是公司今年业绩不好,一波大清洗,据说后面还有,从通知降薪到协商完赔偿也就一周,接下来的一周我还带队开发任务,发版到晚上两三点。来接手的前端国庆假期提前两天请假了,我还分配了下个版本的任务...