前端超长列表,虚拟滚动实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>虚拟滚动</title>
<style>
.container {
width: 300px;
height: 500px;
overflow: hidden;
border: 1px solid #ccc;
margin-top: 50px;
}
.scroll-box {
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
position: relative;
}
.scroll-height-main{
width: 100%;
position: absolute;
top: 0;
left: 0;
}
.list-box{
overflow: hidden;
}
.item {
width: 100%;
height: 50px;
display: flex;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
box-sizing: border-box;
position:absolute;
}
</style>
</head>
<body>
<div class="container">
<div class="scroll-box">
<div class="scroll-height-main"></div>
</div>
</div>
<script>
const scrollBoxDom = document.querySelector('.scroll-box')
const scrollHeightMainDom = document.querySelector('.scroll-height-main')
const itemHeight = 50
// 缓冲条数
const buffer = 2
// 最多支持40w数据
const list = Array.from({ length: 100000 }, (_, index) => `这是第${index + 1}个元素`)
const itemCount = list.length
// 默认出现滚动条
scrollHeightMainDom.style.height = (itemCount * itemHeight) + 'px'
// 移除之前的dom
function clearChildDom() {
scrollBoxDom.querySelectorAll('.item').forEach(itemDom=>{
itemDom.remove()
})
}
// 插入dom
function insertDom(start, end) {
clearChildDom()
const createItem = (index)=>{
const newChild = document.createElement('div')
newChild.className = 'item'
newChild.style.transform = `translateY(${index * itemHeight}px)`;
newChild.innerHTML = list[index]
return newChild
}
for (let i = start; i <= end; i++) {
scrollBoxDom.appendChild(createItem(i))
}
}
// 初始化
insertDom(0, Math.ceil(scrollBoxDom.offsetHeight / itemHeight))
scrollBoxDom.addEventListener('scroll', () => {
const scrollTopVal = scrollBoxDom.scrollTop
/**
* @target 得到起始下标
* 滚动距离可以放多少个子元素
* 向下取整后-缓冲数量
* 再和最小index取最大值
*/
const startIndex = Math.max(0,Math.floor(scrollTopVal / itemHeight) - buffer)
/**
* @end 得到结束下标
* 向上取整(可视区域可以放多少子元素) + 起始下标 + 缓冲区*2 多缓冲一些
* 再和最大index取最小值,endIndex不能超出list最后一项
*/
const endIndex = Math.min(itemCount-1, Math.ceil(scrollBoxDom.clientHeight / itemHeight) + startIndex + buffer*2)
insertDom(startIndex, endIndex)
})
</script>
</body>
</html>
原文地址:https://blog.csdn.net/weixin_44260173/article/details/143860624
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!