第六十期:前端一次渲染30000条数据难吗
这里记录工作中遇到的技术点,以及自己对生活的一些思考,周三或周五发布。
封面图
很明显,难,是真的难!不是一般的难!
关于前端性能优化,有很多文章写的都很详细,大体内容都是减少dom操作,压缩代码文件,减小图片,使用cdn之类的。这些都是一些普遍的问题,因为从根本来看,影响前端性能的因素有三点,一是网络带宽,二是接口返回时间,三是界面渲染速度。
这三点中,前两个问题我觉得可以划分为一类问题,真正跟前端关系比较密切的是界面渲染速度。那么界面渲染速度取决于什么呢?
一般来说,我们会想到dom元素,dom元素越多,界面渲染的时间越长。这个我们都知道,但是其实我们忽略了一个比较重要的点:目前前端开发中主要使用Vue及React框架。这两种框架都是基于数据驱动的,所以我们在渲染列表或者表格时,影响界面渲染效率的因素其实是数据的计算时间。
那么是什么影响了数据的计算时间呢?很明显,数据量和js的执行效率。数据量越小,js的执行效率越高,计算结果返回的就越快,界面渲染的时间就越短。数据越大,js的执行效率越低,界面渲染的时间就越长。
js的执行效率一般我们可以理解为js循环的效率,我们可以将它看作成一个固定值。执行下面的代码,大致需要5s钟时间:
function test(){
let start = performance.now()
for(let i=0;i<30000;i++){
console.log('i')
}
let end = performance.now()
console.log(end-start) // 5000ms
}
这只是个简单的循环30000个数值,循环体中并没有其他复杂的操作,但是当我们的循环体中有其他复杂的操作,比如判断,对象赋值,或者嵌套一层或多层内循环时,花费的时间则呈现出指数级的增长。
尤其是当单条数据中的属性不固定的时候,一般来说,我们遇到的表格,单条数据里面属性十几,一二十个就算多的了,但是有时候可不止一百个!
是的,你没有看错,不止一百个!这个时候,遍历一个数组,数组长度28000,单条数据属性100个,那你只能等,没有办法。
举个现实中的例子:
最近做的项目中有一个多栏表头的表格,表头的数量不固定,表头分组的数量也不固定,表头最多有720列,每个表头分组中最多有8列,分组表头需要动态计算,表格数据也需要前端动态计算,这样算下来,一条数据中最多会有7208n个字段,n是必须的字段,并且后端没有分页,一次性返回30000条数据。
这种情况下,靠前端优化,你怎么优化?这个时候,你会发现,一旦数据量超过某个临界值,界面九成的概率是要崩溃掉的,即便不崩溃,也需要等个十几分钟。
也许有人会说,这种情况用什么切片了,数据分组了。数据分组其实就是分时函数,比如原先你一次性生成10000条数据,那么现在每秒钟生成500条。这种效果在上面的场景中其实起到的优化的效果也并不明显,但是也没什么特别好的方法。
我这里的分时函数是这样的:
const genTableDataSource = (arr) => {
let obj = {}
if (arr.length) {
arr.map((item) => {
data.xAxis.map((v) => {
if (item.dimension === v.dimension) {
obj.store_name = item.store_name
for (let k in coreIndexListObj) {
obj[`${v.title}${coreIndexListObj[k].field}`] =
item[coreIndexListObj[k].field]
}
}
})
})
}
tableDataSource.push(obj)
console.log('tableDataSource---', tableDataSource)
}
const timeChunk = (arr, fn, count) => {
let keys = Object.keys(arr),
t
const start = () => {
for (let i = 0; i < Math.min(count || 2, keys.length); i++) {
let obj = arr[keys.shift()]
console.log('obj---', obj)
fn(obj)
}
}
return function() {
self.timer = setInterval(() => {
if (keys.length == 0) {
clearInterval(self.timer)
}
start()
}, 500)
}
}
let genFinal = timeChunk(rebuildList, genTableDataSource)
console.log('genFinal--', genFinal)
genFinal()
个人感觉前端性能优化这个问题,还是需要具体问题具体分析,在一般的项目里,真的有那么多场景需要去优化吗,这个未必,但是我们需要针对一些特定的场景有自己的解决方案。
可以从技术上进行优化,分页,图片压缩,web缓存,nginx缓存,cnd等等。也可以结合非技术方案,优化交互方案,减少业务复杂度等等。
总之,关于性能优化这个东西,需要根据具体情况具体分析,不能人云亦云。
最后
- 公众号《JavaScript高级程序设计》
- 公众号内回复”vue-router“ 或 ”router“即可收到 VueRouter源码分析的文档。
- 回复”vuex“ 或 ”Vuex“即可收到 Vuex 源码分析的文档。
感谢您的点赞,转发,关注。
转载自:https://juejin.cn/post/7062526457607634958