跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端算法

前端虚拟列表实现原理与优化实践

介绍前端虚拟列表的实现原理与优化方案。针对长列表渲染导致页面卡顿的问题,阐述了只渲染可见区域元素的核心机制。通过对比错误渲染方式,展示了基于 React 的手动实现方法,以及使用 react-window 和 vue-virtual-scroller 库的最佳实践,旨在提升大数据量列表的性能表现。

月亮邮递员发布于 2026/4/6更新于 2026/9/1086 浏览
前端虚拟列表实现原理与优化实践

为什么你需要虚拟列表

最近看到一个项目,一个下拉列表有 5000 个选项,全部渲染导致页面卡死。一次性渲染大量 DOM 节点会严重影响性能。

反面教材
// 反面教材:一次性渲染所有数据
function BigList({ items }) {
  return (
    <ul style={{ height: '400px', overflow: 'auto' }}>
      {items.map(item => (
        <li key={item.id} style={{ height: '50px' }}>
          {item.name}
        </li>
      ))}
    </ul>
  );
}

// 使用
// <BigList items={Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }))} />

渲染 10000 个 DOM 节点会导致浏览器负载过高,影响用户体验。

前端虚拟列表的正确姿势

1. 基础虚拟列表实现
import { useState, useRef, useMemo, useCallback } from 'react';

function VirtualList({ items, itemHeight, containerHeight }) {
  const [scrollTop, setScrollTop] = useState(0);
  const containerRef = useRef(null);

  // 计算可见区域
  const visibleCount = Math.ceil(containerHeight / itemHeight);
   totalHeight = items. * itemHeight;

  
   startIndex = .(scrollTop / itemHeight);
   endIndex = .(startIndex + visibleCount + , items.);

  
   visibleItems = ( {
     items.(startIndex, endIndex);
  }, [items, startIndex, endIndex]);

  
   offsetY = startIndex * itemHeight;

   handleScroll = ( {
    (e..);
  }, []);

   (
    
  );
}

 () {
   items = .({ :  },  ({ : i, :  }));
   ;
}
const
length
// 计算起始和结束索引
const
Math
floor
const
Math
min
1
length
// 获取可见项
const
useMemo
() =>
return
slice
// 偏移量
const
const
useCallback
(e) =>
setScrollTop
target
scrollTop
return
<div ref={containerRef} style={{ height: containerHeight, overflow: 'auto' }} onScroll={handleScroll}> <div style={{ height: totalHeight, position: 'relative' }}> <div style={{ transform: `translateY(${offsetY}px)` }}> {visibleItems.map((item, index) => ( <div key={item.id} style={{ height: itemHeight }} className="virtual-list-item"> {item.name} </div> ))} </div> </div> </div>
function
App
const
Array
from
length
10000
(_, i) =>
id
name
`Item ${i}`
return
<VirtualList items={items} itemHeight={50} containerHeight={400} />
2. 使用 react-window
import { FixedSizeList as List } from 'react-window';

function VirtualList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style} className="list-item">
      {items[index].name}
    </div>
  );

  return (
    <List height={400} itemCount={items.length} itemSize={50}>
      {Row}
    </List>
  );
}

function App() {
  const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }));
  return <VirtualList items={items} />;
}
3. 使用 vue-virtual-scroller
<template>
  <RecycleScroller :items="items" :item-size="50" key-field="id" v-slot="{ item }">
    <div>{{ item.name }}</div>
  </RecycleScroller>
</template>

<script setup>
import { RecycleScroller } from 'vue-virtual-scroller';
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';

const items = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }));
</script>

<style>
.scroller {
  height: 400px;
}
.item {
  height: 50px;
  display: flex;
  align-items: center;
  padding: 0 20px;
}
</style>

实战技巧:虚拟列表指南

1. 虚拟列表原理
  1. 只渲染可见项:只渲染视口内的元素。
  2. 计算偏移量:通过 transform 移动内容。
  3. 动态高度支持:预估高度或动态计算。
2. 最佳实践
  1. 固定高度:优先使用固定高度,性能好。
  2. 缓冲区域:上下多渲染几个 item,避免白屏。
  3. 滚动优化:使用 requestAnimationFrame。

目录

  1. 为什么你需要虚拟列表
  2. 反面教材
  3. 前端虚拟列表的正确姿势
  4. 1. 基础虚拟列表实现
  5. 2. 使用 react-window
  6. 3. 使用 vue-virtual-scroller
  7. 实战技巧:虚拟列表指南
  8. 1. 虚拟列表原理
  9. 2. 最佳实践

更多推荐文章

查看全部
  • Flutter 使用 wasm_ffi 在鸿蒙端调用 WebAssembly 实战
  • Scrapy Spider 基础:从项目结构到数据管道
  • Git 历史回溯实战:查看和恢复之前的版本及误删文件
  • AI 大模型的掌握与运用技巧
  • 北京发布首批 10 个行业大模型典型应用案例
  • PyWebIO 表单性能优化与高并发提交场景解析
  • AI 绘画提示词工具网站推荐与使用指南
  • 2026 年主流 AI Agent 框架横评:OpenClaw 系列对比与场景推荐
  • Claude Code + Figma:AI 辅助设计原型工作流实战
  • DeepSeek-R1-Distill-Llama-8B 部署:Docker Compose 推理服务
  • Apache IoTDB 深度解析时序数据聚合的 GROUP BY 与 HAVING 子句
  • OpenAI 发布最强推理模型 o1:性能超越 GPT-4o 详解
  • 无人机路径规划算法详解:原理、应用与优化
  • VS Code 集成 Git 开发工作流实战指南
  • 二叉树深度计算与先序序列重构算法解析
  • 大模型基于 llama.cpp 量化详解
  • OpenClaw AI Agent 框架核心优势与技术架构解析
  • iOS 26 系统兼容适配:UITabBar 液态玻璃效果与 WiFi SSID 获取
  • Stable Diffusion 3.5 FP8 镜像部署与量化技术详解
  • Linux 环境下 OpenClaw 安装、初始化与 Web UI 配置

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online