MST

星途 面试题库

面试题:JavaScript 复杂场景下的滚动加载与虚拟列表结合实现

假设现在有一个超长列表需要实现滚动加载,同时为了优化性能要结合虚拟列表技术(只渲染可视区域内的列表项)。请详细说明在JavaScript中如何实现这一复杂场景,包括整体架构设计、数据管理、滚动监听以及虚拟列表渲染的具体实现方式,并写出核心代码逻辑。
18.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

整体架构设计

  1. 数据层:负责存储整个超长列表的数据。
  2. 视图层:负责渲染可视区域内的列表项。
  3. 控制层:监听滚动事件,计算可视区域,通知视图层更新。

数据管理

  1. 使用数组存储所有列表数据。例如:
const allData = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`);
  1. 定义变量来存储当前可视区域的起始和结束索引。
let startIndex = 0;
let endIndex = 20; // 假设初始可视区域显示20个项

滚动监听

  1. 通过 window.addEventListener('scroll', handleScroll) 监听滚动事件。
  2. handleScroll 函数中,计算当前滚动位置,并根据滚动位置和列表项高度计算出新的可视区域索引。
function handleScroll() {
    const scrollTop = window.pageYOffset;
    const itemHeight = 50; // 假设每个列表项高度为50px
    startIndex = Math.floor(scrollTop / itemHeight);
    endIndex = startIndex + 20;
    renderVirtualList();
}

虚拟列表渲染的具体实现方式

  1. 在HTML中创建一个容器来显示虚拟列表。
<div id="virtualList"></div>
  1. 在JavaScript中,根据可视区域索引从数据数组中截取需要渲染的数据,并渲染到页面。
function renderVirtualList() {
    const virtualList = document.getElementById('virtualList');
    virtualList.innerHTML = '';
    const visibleData = allData.slice(startIndex, endIndex);
    visibleData.forEach((item, index) => {
        const li = document.createElement('li');
        li.textContent = item;
        virtualList.appendChild(li);
    });
}

核心代码逻辑汇总

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Virtual List with Scroll Load</title>
    <style>
        li {
            height: 50px;
            line-height: 50px;
            border-bottom: 1px solid #ccc;
        }
    </style>
</head>

<body>
    <div id="virtualList"></div>
    <script>
        const allData = Array.from({ length: 10000 }, (_, i) => `Item ${i + 1}`);
        let startIndex = 0;
        let endIndex = 20;

        function handleScroll() {
            const scrollTop = window.pageYOffset;
            const itemHeight = 50;
            startIndex = Math.floor(scrollTop / itemHeight);
            endIndex = startIndex + 20;
            renderVirtualList();
        }

        function renderVirtualList() {
            const virtualList = document.getElementById('virtualList');
            virtualList.innerHTML = '';
            const visibleData = allData.slice(startIndex, endIndex);
            visibleData.forEach((item, index) => {
                const li = document.createElement('li');
                li.textContent = item;
                virtualList.appendChild(li);
            });
        }

        window.addEventListener('scroll', handleScroll);
        renderVirtualList();
    </script>
</body>

</html>

上述代码只是一个简单示例,实际应用中可能需要考虑更多细节,如列表项高度不一致、滚动性能优化(如使用 requestAnimationFrame)等。