性能优化问题
在八股文面试过程中会被经常问到如果有十几万条数据如何处理?
**分页加载:** 不要一次性加载和渲染1000条数据,而是将数据分成多个页面或分页加载。只加载并显示当前页面或滚动视图中可见的部分数据。用户可以滚动或翻页来查看更多数据。
**虚拟滚动:** 使用虚拟滚动技术,只渲染用户可见的部分数据。这可以显著提高性能,因为页面上只会存在少量元素。
**搜索和过滤:** 提供搜索和过滤功能,让用户可以根据需要筛选数据,以减少显示的数据量。
**无限滚动:** 当用户滚动到页面底部时,自动加载更多数据。这种方式可以实现平滑的用户体验,同时避免一次性加载大量数据。
**分批渲染:** 将数据分成多个批次,每次渲染一部分数据。可以使用定时器或异步渲染来逐步加载和显示数据。
**懒加载:** 对于图片等资源,使用懒加载技术,只在元素进入可视区域时加载资源。
**使用列表组件:** 使用列表组件,如Vue的`<v-for>`或React的`map`函数,来迭代渲染数据。这些组件通常具有内置的虚拟滚动和性能优化功能。
**前端缓存:** 如果数据不经常变化,可以考虑在前端进行数据缓存,以减少对后端服务器的请求。
**后端分页:** 如果可能的话,从后端请求数据时,使用分页查询来减少每个请求的数据量。
**数据合并:** 如果数据中有大量重复的内容,可以在前端对数据进行合并和去重,以减小数据规模。
**数据压缩:** 如果数据传输量大,可以考虑使用数据压缩技术来减小数据的大小。
**性能优化工具:** 使用浏览器的性能分析工具来检测瓶颈并进行性能优化。
但是在实际的工作中基本是用封装好的组件,自己处理那么多数据还是第一次碰见,其实很混乱不知道如何写,百度和chatGPT大部分是分页,虚拟列表相对是比较多的处理方案。
由于本次维护的项目页面存在全选复选框,导致分页查接口的方法无法实现。公司的后端让我看调接口查10000条数据需要多长时间,我大概看了一下352ms左右,其实是可接受的范围,但是页面渲染那么多数据卡顿的一直转圈,于是任务落到前端的头上,我最开始想着虚拟列表和懒加载这两个方法,但是无从下手,而且任务也在催促当天要发版,于是就想着参照项目之前分页操作使用的scroll-view 可滚动视图区域进行手动分页。
scroll-view
<scroll-view
:scroll-top="myScrollRightTop"
scroll-y
scroll-with-animation
class="right-box"
@scroll="myRightScroll"
@scrolltolower="onScrollBottom"
>
</scroll-view>
data
data:{
foodList: [], //存储的数据
displayedFoodData: [], // 显示的数据
batchSize: 10, // 每次加载的数据数量
currentIndex: 0, // 当前数据索引
}
method
buildFoodList() {
return new Promise((resolve, reject) => {
this.foodList = []
this.currentIndex = 0
findAppletGoodsFoodList({
pageNum: 1,
pageSize: 1000,
}).then(response => {
if (response.errCode === 0) {
// 存储数据
this.foodList = this.$s.clone(response?.data || [])
// 存储数据长度大于10时,截取十条数据显示,当前数据索引 + 1
if(this.foodList.length > 10) {
this.displayedFoodData = this.foodList.slice(0,10)
console.log(this.displayedFoodData);
this.currentIndex = 1
} else {
// 否则 将存储的数据直接赋值给显示数据
this.displayedFoodData = this.foodList
}
} else {
this.foodList = []
this.$s.toast(response.message)
}
}).catch(error => {
this.foodList = []
}).finally(() => {
resolve()
})
})
},
/**
* @description scroll触底
*/
onScrollBottom() {
// 节流
this.$s.throttle(() => {
// 因为在获取foodList数据时,判断长度当前数据索引是1,所以当scroll触底时 (当前数据索引 + 1) X 10 判断是否大于10且小于foodList的长度
if (this.batchSize < (this.currentIndex + 1) * this.batchSize <= this.foodList.length) {
// 当前数据索加1
this.currentIndex++
// 截取十个数据
const temp = this.foodList.slice((this.currentIndex-1) * this.batchSize, this.currentIndex * this.batchSize) //
// 将截取的数据存入到显示的数据内
this.displayedFoodData.push(...temp)
// (当前数据索引 + 1) X 10 判断是否大于foodList的长度
} else if ((this.currentIndex + 1) * this.batchSize > this.foodList.length) {
// 显示数据的长度小于存储数据的长度,将不满十条数据的截取存入显示数据内
if (this.displayedFoodData.length < this.foodList.length) {
const temp = this.foodList.slice((this.currentIndex * this.batchSize, this.foodList.length-1))
this.displayedFoodData.push(...temp)
} else {
this.$s.toast('没有更多了')
}
} else {
this.$s.toast('没有更多了')
}
})
},
在onScrollBottom方法内处理显示数据的判断条件,当时写的时候感觉条件的判断是有问题的,但是任务比较急为了快点解决问题就没有优化。
到此为止是处理uniapp中要实现一次性加载10000条数据渲染问题。
菜鸟处理问题能力有限,应该有更好的方法实现一次性加载10000条数据渲染问题,希望各位大佬赐教。