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>
放弃安逸,持续努力——成长