背景
在做机构版的时候,一开始为机构设置的人数上限为100,心想就100个,因此前端直接获取全部直接渲染,没有做分页。
这时甲方忽然提出,需要总人数超过400,因为时间比较紧急,我们仅仅只是把请求改了,没有去做对大型数据的优化。
等到测试的时候(400个人数),发现页面的阻塞时间超过1秒,因此有了这篇文章
技术路线
采用的是vue3+ elPlus,
因为使用的是el-table
,以及和产品ui沟通,最后选择和病例列表一样使用infinite-scroll
的解决方案
因为el-table,自身没有无限滚动的方案,所以选择了第三方集成的库,
el-table-infinite-scroll - npm (npmjs.com)
使用方案
npm install --save el-table-infinite-scroll
局部使用
<template>
<el-table
:infinite-scroll-disabled="scrollDisabled"
v-el-table-infinite-scroll="load"></el-table>
</template>
<script setup>
import { default as vElTableInfiniteScroll } from "el-table-infinite-scroll";
const scrollDisabled = ref(false)
const page = ref(0)
const data = computed(() => orgStore.list)
const load= ()=>{
page.value++
new Promise(()=>{}).then((res)=>{
let data = res.data
if (page.value * data.pageCount >= data.totalCount) {
scrollDisabled.value = true
}
})
}
</script>
优化过后的性能
上面的为50条数据的渲染曲线,下面的为400条数据的曲线,页面渲染总时间大概为300/1800(8倍),页面阻塞时间大概为430/2400
思考:我们知道,从请求数据到渲染所有页面,包括网络请求
,js执行(虚拟dom比较,响应式等)
,真实dom渲染(真实dom树渲染)
等等阶段,那么从50条到400条,到底那些地方优化最多?
网络请求
50条数据,平均请求时间大概在50ms,400条数据,平均请求时间大概在100ms,
50条数据大概1.5kb,400条大概6.2kb
根据上图也可以看出,服务器相应时间占大头,大概40ms,但网络的下载时间成倍数增加,直接增加12ms(20多倍,大概是大型数据的数据拼接)
浏览器的执行
其实js执行和dom渲染是交替执行的,但即便如此,当数据量为400的时候其第一次阻塞的执行时间大概为1400ms,其中占500+ms,渲染时间占700+ms,这也就是说js的执行时间大概为500ms,500ms执行完毕后,会进行dom的渲染(nextTick的执行),此时dom的渲染时间大概为700ms,这里的700ms基本可以确定为是真实dom的渲染,然后会进行400ms的渲染,这里的动画渲染应该是浏览器的渲染时间,大概是400ms,400ms执行完毕后,页面就已经完全渲染成功,此时已经能够看到页面,但无法对页面进行任何操作,之后页面继续进行各种事件的绑定,大概是700ms,此时完整的页面渲染完成
上面的页面可能过于冗余,我们简化一下就是
- 页面请求,虚拟dom比较 400+ms
- 真实dom添加,700+ms
- 浏览器渲染,400+ms
- 页面事件的绑定,700+ms
而变成50条的数据,上面的行为就变成
- 页面请求,虚拟dom比较 100+ms
- 真实dom添加,100+ms
- 浏览器渲染,70+ms
- 页面事件的绑定,100+ms
Q.E.D.