欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

利用链表数据结构优化页面渲染

最编程 2024-05-03 21:27:26
...

需求及所遇问题

页面数据的渲染优化有很多种方法,如果遇到列表数据很多的情况下,通常用的方法就是进行分页请求,但有时后台并不会将数据进行分页加载,把数据全部返回给了前端,这时前端有没有方法去优化渲染呢? 如图: 需求:点击左侧导航,有子列表右侧实现相应滚动,没有子列表,实现请求跳转页面;滑动右侧,左侧导航active相应改变

数据结构:大概如下:

data = [
 {id:1, children:[{id: 11, name: '', img: ''}]}, 
 {id: 2},
 {id:3, children:[{id:41, name:''}], 
 {id:4}
]

问题:后台返回的数据可能会是超100,甚至200条数据,造成页面渲染慢,怎么优化?

基于项目的需求,以及数据的形式,因为后台不进行分页返回,那么只能是前端优化,可是如何优化呢?

既然是因为渲染数据过多造成的渲染问题,那么就进行首屏优化,这个简单,我们通过截取数组,可以先渲染数组前面20条。但另一个问题来了,怎么在滚动或者点击的时候加载相应的数据呢?

滚动还简单些,按顺序将数组push上去。但另一个左侧点击,渲染相关的数据,并且当active类的子列表数组很少时,我们还需要显示离active类相邻的前后有子类的数据,问题是每个大分类不一定有子列表,而且当前active的前后分类的数据也是不一定就有子数据。显然,我们没法通过数组的索引知道当前active分类与其相邻的最近有子列表的大类是哪个。当然,每次都去循环获取,也可以得到,但显然这种方式不太友好。

我们需要另一种数据存储结构,这个数据结构能让我们拿到每个单项,都能知道它前后有子列表的大类是哪个。这时,链表的数据结构就可以解决这个问题,让每个单项之间具有联系。

什么是链表

数组的子项联系,来自于索引,它们的之间的关系是有序的,但链表是一种非顺序的存储结构,各项之间的联系是通过指针的链接顺序来实现。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

举个例子,甲乙丙丁四人,各自都不知道自己在队伍里排几号,但是甲知道排在他前面的是乙,排在他后面的是丁,丙知道排在他前面的是丁,没有人排在他后面,那么我们很容易就可以知道他们的顺序是乙——甲——丁——丙。这个就是链表的存储数据结构,我们可以通过单项的数据找到它前后的联系,进而一项一项串起来。

如何设计链表

链表数据结构的基本思路:pre代表前一项的指针,next表示后一项的指针。显然,首项,没有前一项,用pre为null表示,尾项,没有后一项,用next为null表示

我们的需求是记录每个有children前后的联系,实现思路大概如下,代码实现:

let pre = null;
let next = null;
let dataObj = {}
data.forEach((item, index)=>{
	if(item.children && item.children.length > 0){
    	if(index===data.length-1) {
    		next = null
    	} else {
    		next = data[index+1].id
    	}
    	item.next = next
    	item.pre = pre
    	pre = item.id
        dataObj[item.id] = item
    }
})

这里用对象存储是为了在每次点击获取单个数据项时,不必进行循环获取

滚动添加数据

但滚轮向下滚动时,进行添加数据渲染,基本思路,根据当前active大类(有children)的id,进行判断:

  • 当前active大类还有children项未添加显示,继续添加
  • 当前active大类children项已全部添加完,需添加next大类的children
  • 点击选中左侧,当前active大类children项已全部添加完,next大类的children也全部添加完,但页面还有空间显示,需添加pre大类的children

代码这里就不写了,但这里我们可以看到,通过链表,我们可以减少循环遍历,很快就能知道单项的前后联系,实现快速查找的过程。

结语

页面优化的方式有很多,当我们需要从数据的单项知道某种联系,但是数组的索引无法满足的话,可以考虑一下用链表的形式,可以更加快速有效的获取到数据。另外,本文写的比较简略,仅提供思路和方法参考,详细的建议可以去查找资料。