js实现虚拟表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>虚拟表格</title>
<style>
* {
padding: 0;
margin: 0;
}
#list {
width: 300px;
height: 500px;
overflow-y: auto;
position: relative;
}
#parent {
position: relative;
width: 100%;
}
#content {
-webkit-willChange: 'transform';
willChange: 'transform';
position: absolute;
width: 100%;
left: 0;
top: 0;
}
#bg {
position: absolute;
z-index: 10;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fff;
opacity: 0;
display: none;
}
.item {
min-height: 50px;
margin-bottom: 5px;
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div id="list">
<div id="parent">
<!-- 用来装载内容 -->
<div id="content"></div>
<!-- 用来遮挡渲染内容,避免鼠标在不断渲染的content上面的时候导致卡顿无法触发滚动 -->
<div id="bg"></div>
</div>
</div>
<script>
let itemNum = 100; // 内容总数
let itemHeight = 52; // 每个内容单元高度
let list = document.getElementById('list')
let parent = document.getElementById('parent')
parent.style.height = `${itemNum*itemHeight}px` // 内容总高度撑开滚动条
let content = document.getElementById('content')
let bg = document.getElementById('bg')
let cNum = Math.ceil(list.offsetHeight / itemHeight) // 可视区域个数
let startIndex = 0 // 可视区域开始index
let endIndex = startIndex + cNum // 可视区域结束index
let data = [...new Array(itemNum).keys()] // 生成所有数据
// 渲染初始数据
data.slice(startIndex, endIndex).forEach(item => {
let div = document.createElement('div')
div.innerHTML = item
div.setAttribute('class', 'item')
content.appendChild(div)
})
let timer = null; // 滚动定时器,用于检测是否滚动结束
let scrollTop = 0; // 当前滚动条高度
let scrollEndTop = 0; // 停止时滚动条高度
function scrollCallBack() {
clearTimeout(timer);
timer = setTimeout(isScrollEnd, 500);
scrollTop = list.scrollTop
bg.style.display = 'block'
let sTop = Math.max(list.scrollTop, 0) // 滚动距离,最小取0
startIndex = Math.floor(sTop / itemHeight) // 可视区域开始index
endIndex = startIndex + cNum // 可视区域结束index
content.style.transform = `translateY(${startIndex*itemHeight}px)` // 内容区域偏移
// 新的数据渲染
let newData = data.slice(startIndex, endIndex)
let html = ''
newData.forEach(item => {
html += `<div class="item">${item}</div>`
})
content.innerHTML = html
}
// 判断是否滚动结束,将bg遮罩层隐藏
function isScrollEnd() {
scrollEndTop = list.scrollTop;
if (scrollTop === scrollEndTop) {
console.log('滚动条停止滚动');
bg.style.display = 'none'
}
}
scrollCallBack()
list.addEventListener('scroll', scrollCallBack)
</script>
</body>
</html>
放弃安逸,持续努力——成长

浙公网安备 33010602011771号