假如有十万条数据,前端应该怎么处理?
虚拟列表
虚拟列表其实是按需显示的一种实现,即只对可见区域进行渲染,对非可见区域中的数据不渲染或部分渲染的技术,从而达到极高的渲染性能。
虚拟列表优势
虚拟列表可以解决一次性渲染数据量过大时,页面卡顿,(比如: table 不分页并且一次性加载上万条复杂的数据)
实现步骤
数据列表初始化 :10 万条数据
// 初始化列表数据
const getDatas = () => {
const datas = [];
for (let i = 0; i < 100000; i++) {
datas.push(`${i} Item`);
}
return datas;
};
class App extends React.Componemt{
/*
* 假设每项数据的dom元素高度为30px
* 实际项目可能每项高度不一样
* */
static = itemH = '30'
constructor(props){
super(props)
// 获取dom结构
this.virtualList = React.creatRef()
// 计算总高度
const totalH = data.length * App.itemH + 'px'
this.state = {
data:[] // 可是区域数据
totalHeight:totalH // 列表总高度
transform:'' // 偏移
}
}
componentDidMount(){
this.updateViewContent()
}
handleScroll = e => {
this.updateViewContent(e.target.scrollTop)
}
updateViewContent = (scrollTop = 0) => {
// 计算区域里能放几个元素
const viewCount = Math.ceil(this.virtualList.current.clientHeight/App.itemH)
// 计算区域开始的索引
const start = Math.floor(scrollTop / App.itemH)
// 计算区域结束索引
const end = start + viewCount
// 截取区域内数据
const viewData = data.slice(start,end)
this.setState({
data:viewData,
// 区域的top设置为起始元素在整个列表中的位置
transform:`translate3d(0,${start * App.itemH})px,0`
})
}
render(){
const {totalHeight,transform,data} = this.state
return (
<div className='virtual-list' onScroll = {this.handleScroll} ref={this.virtualList}>
// css样式:列表的总高度
<div className="virtual-list-height" style={{height: totalHeight}} />
<div className="view-content" style={{transform: transform}}>
{
data.map((item,index)=>{
<div className="view-item" key={index}>{item}</div>
})
}
</div>
</div>
)
}
}
ReactDOM.render(
React.createElement(App),
document.getElementById('app'),
)
CSS 代码
.virtual-list {
position: relative;
height: 500px;
overflow: auto; /*只有这行代码写了,内容超出高度才会出现滚动条*/
border: 1px solid #ddd;
}
.virtual-list-height {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.view-content {
position: absolute;
left: 0;
right: 0;
top: 0;
}
.view-item {
box-sizing: border-box;
padding: 0 5px;
height: 30px;
line-height: 30px;
}