烟台网站制作,大连网络推广平台,网页更改,福州建设网站效果highlight: a11y-dark
虚拟滚动列表#xff0c;虚拟滚动的关键在于只渲染当前视口内可见的数据项#xff0c;而不是一次性渲染所有数据项。这可以显著提高性能#xff0c;尤其是在处理大量数据时。
以下是一个完整的虚拟滚动列表的示例代码#xff1a;
!DOCTYPE htm…
highlight: a11y-dark
虚拟滚动列表虚拟滚动的关键在于只渲染当前视口内可见的数据项而不是一次性渲染所有数据项。这可以显著提高性能尤其是在处理大量数据时。
以下是一个完整的虚拟滚动列表的示例代码
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleVirtual Scrolling/titlestyle#container {width: 500px;height: 700px;margin: 30px;overflow: auto;position: relative;border: 1px solid #ccc;}.item {position: absolute;width: 100%;background-color: #bfc;border-radius: 10px;margin: 2px 0;padding: 10px;box-sizing: border-box;}/style/headbodydiv idcontainer/divscriptconst container document.getElementById(container);const itemHeight 50;const containerHeight 700;const buffer 5;let data [];let visibleData [];let startIndex 0;function loopFun(num) {data Array.from({ length: num }, (_, index) index);handleScroll();}function handleScroll() {const scrollTop container.scrollTop;const visibleStart Math.max(0, Math.floor(scrollTop / itemHeight) - buffer);const visibleEnd Math.min(data.length,visibleStart Math.ceil(containerHeight / itemHeight) buffer * 2);startIndex visibleStart;visibleData data.slice(visibleStart, visibleEnd);renderVisibleData();}function renderVisibleData() {container.innerHTML ;visibleData.forEach((item, index) {const div document.createElement(div);div.className item;div.style.top (startIndex index) * itemHeight px;div.textContent 数据-${item};container.appendChild(div);});}function throttle(func, limit) {let inThrottle;return function () {const args arguments;const context this;if (!inThrottle) {func.apply(context, args);inThrottle true;setTimeout(() (inThrottle false), limit);}};}loopFun(1000);const throttledHandleScroll throttle(handleScroll, 100);container.addEventListener(scroll, throttledHandleScroll);window.addEventListener(beforeunload, () {container.removeEventListener(scroll, throttledHandleScroll);});/script/body
/html上面一大串代码看起来比较难看在下边我会拆开了一点点来说明。先来看一下在页面上的展示效果如下 对比两张效果图可以看到不论怎么滚动页面实际上展示的永远是 23 条数据。
声明的变量
const container document.getElementById(container); // 获取元素
const itemHeight 50; // 每个数据项的高度
const containerHeight 700; // 容器的高度
const buffer 5; // 缓冲区提前加载的数据项数量let data []; // 获取元素
let visibleData []; // 存储当前可视区域的数据项
let startIndex 0; // 当前可视区域的起始索引loopFun() 函数的作用
// 拿到 num 条数据的索引生成新数组。
function loopFun(num) {data Array.from({ length: num }, (_, index) index);handleScroll();
}Array.from() 静态方法从可迭代或类数组对象创建一个新的浅拷贝的数组实例。 handleScroll() 函数的作用
function handleScroll() {/** scrollTop 用于获取或设置一个元素的垂直滚动距离 */const scrollTop container.scrollTop;/*** Math.max() 静态方法返回作为输入参数给出的数字中的最大值* Math.floor() 静态方法始终向下舍入并返回小于或等于给定数字的最大整数** scrollTop / itemHeight 得到当前滚动条所处数据位置* buffer 意味着在可视区域上方和下方各提前加载5个数据项*/const visibleStart Math.max(0, Math.floor(scrollTop / itemHeight) - buffer);/*** Math.min() 静态方法返回作为输入参数给出的数字中的最小者* Math.ceil() 静态方法始终向上舍入并返回大于或等于给定数字的最小整数*/const visibleEnd Math.min(data.length,visibleStart Math.ceil(containerHeight / itemHeight) buffer * 2);startIndex visibleStart;visibleData data.slice(visibleStart, visibleEnd);renderVisibleData();}scrollTop scrollTop 是当前滚动条的位置表示从容器顶部到滚动条当前位置的距离以像素为单位。 itemHeight itemHeight 是每个数据项的高度以像素为单位。假设每个数据项的高度是固定的例如 50 像素。 scrollTop / itemHeight 这个表达式计算当前滚动条位置对应的数据项索引。结果是一个浮点数表示滚动条位置对应的数据项的大致位置。 Math.floor(scrollTop / itemHeight) 使用 Math.floor 将浮点数向下取整得到一个整数索引表示当前滚动条位置对应的数据项的起始索引。 Math.floor(scrollTop / itemHeight) - buffer 减去 buffer确保在可视区域上方提前加载 buffer 个数据项。buffer 是一个缓冲区表示在可视区域外提前加载的数据项数量。例如buffer 设为 5意味着在可视区域上方提前加载 5 个数据项。 Math.max(0, …) 使用 Math.max 确保 visibleStart 不小于 0防止负索引。如果 Math.floor(scrollTop / itemHeight) - buffer 小于 0则 visibleStart 会被设置为 0。 renderVisibleData() 函数的作用
// 处理标签结构及文本的展示
function renderVisibleData() {container.innerHTML ;visibleData.forEach((item, index) {const div document.createElement(div);div.className item;div.style.top (startIndex index) * itemHeight px;div.textContent 数据-${item};container.appendChild(div);});
}相当于生成了一个 div 标签加上 class 属性 item
div classitem数据-1/div然后对这个标签进行循环展示。
{visibleData.map((item, index) (div classitem key{item}数据-{item}/div));
}这一行代码可以详细说一说
div.style.top (startIndex index) * itemHeight px;div.style.top div.style这是 DOM 元素的 style 属性它允许你直接访问和修改元素的内联样式。 top这是 style 对象的一个属性用于设置元素的 top CSS 属性。top 属性定义了元素相对于其父容器的顶部边缘的距离。 (startIndex index) * itemHeight startIndex这是当前可视区域的起始索引表示第一个可见数据项在整个数据数组中的位置。 index这是当前数据项在其可视区域内的索引。例如如果 visibleData 包含 10 个数据项index 会从 0 到 9。 itemHeight这是每个数据项的高度以像素为单位。 准确的来说这是用来计算数据项的垂直位置的。 startIndex index计算当前数据项在整个数据数组中的实际索引。startIndex 是当前可视区域的起始索引index 是当前数据项在其可视区域内的索引。 (startIndex index) \* itemHeight将实际索引乘以每个数据项的高度得到当前数据项的垂直位置以像素为单位。 设置 top 属性 div.style.top (startIndex index) * itemHeight ‘px’将计算得到的垂直位置设置为 div 元素的 top 属性值。这样每个数据项都会根据其在数据数组中的位置被正确地定位在容器中。
示例:
startIndex 10;
index 2;
itemHeight 50;计算过程
startIndex index 10 2 12(startIndex index) _ itemHeight 12 _ 50 600div.style.top 600 px 600px因此这个数据项的 top 属性会被设置为 600px表示它距离容器顶部 600 像素。 作用通过这种方式你可以确保每个数据项在容器中的位置是正确的。即使容器滚动每个数据项也会根据其在数据数组中的位置被正确地定位从而实现虚拟滚动的效果。 throttle() 函数的作用
// 节流处理
function throttle(func, limit) {let inThrottle;return function () {const args arguments;const context this;if (!inThrottle) {func.apply(context, args);inThrottle true;setTimeout(() (inThrottle false), limit);}};
}throttle 函数是一种常用的节流技术用于限制函数的调用频率。它在处理高频事件如滚动、窗口调整大小等时非常有用可以显著提高性能并减少不必要的计算。
示例:
func需要节流的函数。limit节流的时间间隔以毫秒为单位表示在多少毫秒内只能执行一次 func。
// 100 毫秒后执行函数 handleScroll
throttle(handleScroll, 100);底部函数调用
loopFun(1000);调用 loopFun 函数生成 1000 个数据项。 const throttledHandleScroll throttle(handleScroll, 100);使用 throttle 函数对 handleScroll 进行节流处理确保 handleScroll 每 100 毫秒最多执行一次。 container.addEventListener(scroll, throttledHandleScroll);向容器元素添加滚动事件监听器当容器滚动时throttledHandleScroll 函数会被调用。 window.addEventListener(beforeunload, () {container.removeEventListener(scroll, throttledHandleScroll);
});window\.addEventListener(beforeunload, ...)在窗口即将卸载时例如用户关闭页面或导航到其他页面触发的事件。 container.removeEventListener(scroll, throttledHandleScroll)在页面卸载前移除滚动事件监听器避免内存泄漏。