虚拟列表

实现虚拟列表及优化

  • 只渲染当前可视区域
  • 可以维护一个对象池,避免频繁创建和销毁 DOM 元素。在滚动时,重新利用之前创建的 DOM 元素,只更新其内容和位置
  • 尽量减少重排和重绘操作,可以使用 CSS 属性 transform 替代 top 和 left,避免触发布局的重新计算
  • 对滚动事件进行防抖(debounce)和节流(throttle)处理,以减少频繁触发更新列表的次数
  • 使用 createDocumentFragment 减少页面的重绘次数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Optimized Virtual List Example with Throttling</title>
<style>
    .container {
        height: 300px;
        overflow-y: scroll;
    }

    .item {
        height: 50px;
        border: 1px solid #ccc;
        margin-bottom: 5px;
    }
</style>
</head>
<body>
<div class="container" id="list"></div>

<script>
const totalItems = 1000; // 总项目数
const itemsPerScreen = 10; // 每屏显示的项目数
const itemHeight = 50; // 每个项目的高度
const scrollThrottleTime = 100; // 滚动节流时间间隔

const container = document.getElementById('list');
container.style.height = `${itemsPerScreen * itemHeight}px`;

const itemPool = new Map();
let throttleTimer = null;

function createItem(index) {
    const item = document.createElement('div');
    item.className = 'item';
    item.innerText = `Item ${index}`;
    return item;
}

function renderItems(startIndex, endIndex) {
    const fragment = document.createDocumentFragment();
    for (let i = startIndex; i < endIndex; i++) {
        let item = itemPool.get(i);
        if (!item) {
            item = createItem(i);
            itemPool.set(i, item);
        }
        item.style.transform = `translateY(${i * itemHeight}px)`;
        fragment.appendChild(item);
    }
    container.innerHTML = '';
    container.appendChild(fragment);
}

function updateList() {
    const scrollTop = container.scrollTop;
    const startIndex = Math.floor(scrollTop / itemHeight);
    const endIndex = Math.min(startIndex + itemsPerScreen, totalItems);

    renderItems(startIndex, endIndex);
}

function throttleUpdateList() {
    if (throttleTimer) {
        return;
    }

    throttleTimer = setTimeout(() => {
        updateList();
        throttleTimer = null;
    }, scrollThrottleTime);
}

updateList();
container.addEventListener('scroll', throttleUpdateList);
</script>
</body>
</html>

总结

想尽一切办法减少 dom 数和操作 dom 的次数

发布日期:
分类:css前端

发表评论

您的电子邮箱地址不会被公开。