问题一、假如给出100条数据信息,我们将如何渲染它?
100条数据库的3D渲染量并不大,能直接3D渲染,react伪代码如下所示:
let originData = new Array(100).fill(1)
originData.map((item,index) => {
return <div>{index}</div>
})
但是如果是1000条呢?那这时坚信每个人都不会去立即3D渲染。
难题二、怎么优化3D渲染100条数据信息?
提升3D渲染有许多种方法,这儿我们采用翻转时固定不动dom总数
的思路。对这样的对策的概念如下所示:
对大数据量(假设数据信息总产量为m)3D渲染的现象,我们采用分次3D渲染的形式,一次只3D渲染n个,Math.ceil(m / n) 次所有3D渲染结束。
1、3D渲染全过程解读
下面我们就各自来解读下上图中的2个情况:
一、情况1
数据信息总产量是100,复位页面中只展现5个,翠绿色框意味着父器皿,5条数据信息高度 > 父容器相对高度,因此父器皿形成了下拉列表。
二、情况2
由情况1往下翻转而成。这时有3种情况:
- a、情况1往下
翻转了什么条数据信息
才变成状态2? - b、情况2的dom总数怎么是11条?
- c、情况2-5的dom总数为啥增长?
针对难题a,在这里我们称之为往下完整的翻转了 1条
数据信息获得状态2。那样在这里我们定义一个变量scrolledDataCount
(伪代码如下所示),用以纪录翻转了什么条完整的数值数据。
let scrolledDataCount = Math.floor(翻转完的间距 / 每一个数值数据高度);
针对难题b,大家首先要明确是指,父器皿在滚动的情况下,信息是动态性转换的,所以我们需要提取数据信息
来实现这种效果。在提取数据信息
以前,大家还要考虑到的一个问题便是提取数据信息的时间段
,那样下面来各个击破。
三、提取数据信息的时间段
提取数据信息的时间段大伙儿追究其,接下来我们要求提取数据信息的时间段如下所示:
1、如果这时dom总数低于15,那样这时就需要不断的push
2、假如dom总数 >= 15,那样这时就需要不断的update数据,并且保证dom总数 == 15
四、提取数据信息的思路
这里边我们使用slice来提取二维数组,所以我们需要了解startIndex与endIndex。伪代码如下所示:
// 翻转完的信息量 - 5 < 0 相对应的机会是push
// 翻转完的信息量 - 5 >= 0 相对应的机会是update
let startIndex = 翻转完的信息量 - 5 < 0 ? 0 : 翻转完的信息量 - 5;
let endIndex = 每一次要载入的信息量(5) 每一页展现的信息量(5) 翻转完的信息量(在增长或是下降);
因为endIndex随时都在变,而且翻转完的信息量在增长,因此情况2-5的dom数量在增长。难题c到这儿就能解决。
对于难题b,我们能来分析一下,父器皿往下翻转1条数据信息,这时的startIndex == 0,endIndex = 5 5 1, 因此这时的dom数量是11(data.slice(0, 11).length)。
2、实例编码
import React from 'react';
export default class Practice extends React.Component {
constructor(props){
super(props);
this.state = {
allData: new Array(200).fill(1).map( (item, index) => ({ name: index }) ),
dataItemHeight: 200, // 每一个每日任务高度
onePageViewAllDataCount: 5, // 1页展现几个每日任务总数
viewDataObject: {
startIndex: 0,
endIndex: 5
},
fatherComponent: React.createRef(),
onePageViewAllData: [], // 一页展现的所有数据
}
}
// 部件翻转
componentScroll = (event) => {
const { fatherComponent } = this.state;
let scrolledDataCount = 0; // 翻转完的详细数据信息总数
if (fatherComponent.current){
scrolledDataCount = Math.floor(Number(fatherComponent.current?.scrollTop || 0) / 200);
let startSize = scrolledDataCount - 5;
let endSize = 5 scrolledDataCount 5;
this.setState(state => {
return {
...state,
viewDataObject: {
startIndex: startSize < 0 ? 0 : startSize,
endIndex: endSize
}
}
}, () => {
this.setState(state => {
return {
...state,
onePageViewAllData: state.allData.slice(state.viewDataObject.startIndex, state.viewDataObject.endIndex)
}
});
})
}
}
// 复位,提取5个每日任务
componentDidMount(){
this.setState(state => {
return {
...state,
onePageViewAllData: state.allData.slice(state.viewDataObject.startIndex, state.viewDataObject.endIndex)
}
})
}
render(){
const { allData, dataItemHeight, fatherComponent, onePageViewAllData } = this.state;
return <div className = 'virtually-box'>
<div className = 'virtually-component' ref={fatherComponent} onScroll={this.componentScroll}>
<div className = 'virtually-component-data'>
{
onePageViewAllData.map(item => { return <div className = 'virtually-component-data-item' style={{ height: `${dataItemHeight}px` }}>
{item.name}
</div>
})
}
</div>
</div>
</div>
}
}
3、实例实际效果
难题三、怎样获得止跌机会?
相信这些我想大家广为人知了,公式计算如下所示:
if (father.scrollTop father.clientHeight >= father.scrollHeight){
return true;
}
return false;
简单概括
1、本文仅仅完成了非常简单、最基本的虚似目录(它游戏的玩法有许多)。热烈欢迎大神们在评论区拓展。
2、实际上虚似目录的本质就是固定不动dom总数
, 只要你能够分次3D渲染大数据量的list,并且能确保dom总数固定不动,或许你完成的便是虚似目录。假如在学习过程中出现发现的问题,热烈欢迎发表评论评价,明天再见啦。
参照
「前面升阶」性能卓越3D渲染十万条数据信息(虚似目录)