性能飙升50%,react-virtualized-list如何优化大数据集滚动渲染
在处理大规模数据集渲染时,前端性能常常面临巨大的挑战。本文将探讨 react-virtualized-list 库如何通过虚拟化技术和 Intersection Observer API,实现前端渲染性能飙升 50% 的突破!除此之外,我们一同探究下该库还支持哪些新的特性和适用场景。
如果你正在寻找解决大数据集渲染瓶颈的方法,或是希望提升前端应用的响应速度,这篇文章将为你带来全新的启发与实用的解决方案。
什么是虚拟化?
虚拟化技术,顾名思义,是一种通过仅渲染当前用户可见的数据项,而不是整个数据集,来优化性能的技术。这种技术在处理大量数据时尤为重要,因为它显著减少了 DOM 节点的数量,从而提高了性能。通过虚拟化,可以在用户滚动列表时动态加载和卸载元素,保持界面流畅。

react-virtualized-list 简介
react-virtualized-list 是一个专门用于显示大型数据集的高性能 React 组件库。它同时适用于 PC 端和移动端,通过虚拟化技术实现了延迟加载和无限滚动功能,尤其是非常适合需要高效渲染和加载大量数据的应用场景,如聊天记录、商品列表等。
此外,react-virtualized-list 库还提供了场景适用的效果展示和示例代码。
核心特性
- 高性能:仅渲染当前视口内的元素,显著减少 DOM 节点数量。
- 延迟加载:动态加载数据,避免一次性加载大量数据带来的性能问题。
- 无限滚动:支持无限滚动,用户可以持续滚动查看更多内容。
- 自定义渲染:提供灵活的 API,允许开发者自定义列表项的渲染方式。
- 视口内刷新:支持自动刷新视口内的内容,确保数据的实时性。
安装和基本用法
安装
可以通过 npm 或 yarn 轻松安装 react-virtualized-list:
npm install react-virtualized-list
# 或者
yarn add react-virtualized-list
基本用法
下面是一个简单的示例,展示了如何使用 react-virtualized-list 创建一个无限滚动的虚拟化列表:
import React, { useState, useEffect } from 'react';
import VirtualizedList from 'react-virtualized-list';
import './style/common.css';const InfiniteScrollList = () => {const [items, setItems] = useState([]);const [hasMore, setHasMore] = useState(true);const loadMoreItems = () => {// 模拟 API 调用setTimeout(() => {const newItems = Array.from({ length: 20 }, (_, index) => ({id: items.length + index,text: `Item ${items.length + index}`}));setItems(prevItems => [...prevItems, ...newItems]);setHasMore(newItems.length > 0);}, 1000);};useEffect(() => {loadMoreItems();}, []);const renderItem = (item) => <div>{item.text}</div>;return (<div className='content'><VirtualizedListlistData={items}renderItem={renderItem}containerHeight='450px'itemClassName='item-class'onLoadMore={loadMoreItems}hasMore={hasMore}loader={<div>Loading...</div>}endMessage={<div>No more items</div>}/></div>);
};export default InfiniteScrollList;
/* ./style/common.css */
.content {width: 350px;padding: 16px;border: 1px solid red;margin-top: 10vh;
}
.item-class {height: 50px;border: 1px solid blue;margin: 0px 0 10px;padding: 10px;background-color: #f0f0f0;
}
通过 onLoadMore 和 hasMore 属性实现无限滚动,在用户滚动到列表底部时自动加载更多数据。这种功能常见于滚动加载下页数据。
进阶用法
动态加载数据
为了进一步提高性能,可以使用动态加载技术,只在需要时加载数据。以下是一个示例,展示了如何结合 react-virtualized-list 和动态数据加载:
import React, { useState, useEffect } from 'react';
import VirtualizedList from 'react-virtualized-list';
import './style/common.css';const fetchProductData = async (product) => {return new Promise((resolve) => {setTimeout(() => {resolve({ description: `Description for ${product.name}`, imageUrl: `https://via.placeholder.com/150?text=Product+${product.id}` });}, 500);});
};const fetchProducts = async (page) => {return new Promise((resolve) => {setTimeout(() => {const products = Array.from({ length: 10 }, (_, i) => ({id: page * 10 + i,name: `Product ${page * 10 + i}`}));resolve(products);}, 500);});
};const DynamicInfiniteList = () => {const [products, setProducts] = useState([]);const [hasMore, setHasMore] = useState(true);const [page, setPage] = useState(0);const loadMoreProducts = async () => {const newProducts = await fetchProducts(page);setProducts(prevProducts => [...prevProducts, ...newProducts]);setPage(prevPage => prevPage + 1);if (newProducts.length < 10) setHasMore(false);};useEffect(() => {loadMoreProducts();}, []);return (<div className='content'><VirtualizedListlistData={products}renderItem={(product, data) => (<div><h2>{product.name}</h2><p>{data ? data.description : 'Loading...'}</p>{data && <img src={data.imageUrl} alt={product.name} />}</div>)}itemClassName='item-class-dynamic'fetchItemData={fetchProductData}onLoadMore={loadMoreProducts}hasMore={hasMore}containerHeight='500px'loader='Loading more products...'endMessage='No more products'/></div>);
};export default DynamicInfiniteList;
/* ./style/common.css */
.content {width: 350px;padding: 16px;border: 1px solid red;margin-top: 10vh;
}
.item-class-dynamic {height: 300px;padding: 20px;border-bottom: 1px solid #eee;
}
注意:在上面代码中,我们使用 onLoadMore 模拟商品列表的滚动加载,并在 VirtualizedList 组件的 fetchItemData 实现了商品详情的动态加载。这对于大数据集下,后端无法一次性返回数据非常有利!
自定义渲染
react-virtualized-list 还提供了自定义渲染功能,开发者可以根据具体需求定制列表项的渲染方式。以下是一个示例,展示了如何自定义列表项的样式和内容:
import React from 'react';
import VirtualizedList from 'react-virtualized-list';const data = Array.from({ length: 1000 }).map((_, index) => ({title: `Item ${index}`,index: index,description: `This is the description for item ${index}.`
}));const ListItem = ({ item, style }) => (<div style={{ ...style, padding: '10px', borderBottom: '1px solid #ccc' }}><h3>{item.title}</h3><p>{item.description}</p></div>
);const itemStyle = {height: '100px',border: '1px solid blue',margin: '0px 0 10px',padding: '10px',backgroundColor: '#f0f0f0'
};const MyVirtualizedList = () => (<div style={{width: '350px', padding: '16px', border: '1px solid red'}}><VirtualizedListlistData={data}itemStyle={itemStyle}renderItem={({ index, style }) => <ListItem item={data[index]} style={style} />}containerHeight='80vh'/></div>
);export default MyVirtualizedList;
通过自定义 ListItem 组件,我们可以轻松定制列表项的样式和内容,提升应用的个性化和用户体验。此外,react-virtualized-list 还提供了其他用法和相关 API,详情请见使用文档。
实现原理
在构建大型 Web 应用时,经常会遇到需要展示大量数据的情况,比如电子商务平台的产品列表等。传统的渲染方式可能会面临性能问题,因为它们需要在页面上同时呈现大量 DOM 元素,导致页面加载缓慢、滚动卡顿等问题。
为了解决这个问题,我们可以使用虚拟化列表来优化渲染过程。而 react-virtualized-list 库的核心在于通过虚拟化技术优化渲染过程。其主要原理包括以下几点:

1. 可视区域监测:利用Intersection Observer API
注意:
react-virtualized-list库在可视区域监测这块使用了另外一个库 react-visible-observer,它是一个基于 Intersection Observer API 的 React 组件库,用于监视元素何时进入视口,并在该元素可见时触发回调函数。这个组件特别适用于实现懒加载、动画触发等功能。
在虚拟化列表的实现中,一个关键步骤是监测可视区域内的元素。传统的方法是通过监听滚动事件并计算每个元素的位置来实现,然而这种方式效率较低。
// 获取需要监测可视性的元素
const elements = document.querySelectorAll('.target-element');// 监听滚动事件
window.addEventListener('scroll', () => {// 计算每个元素的位置elements.forEach(element => {const rect = element.getBoundingClientRect();if (rect.top >= 0 &&rect.left >= 0 &&rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {// 元素在可视区域内// 执行相应操作console.log(`${element} is visible.`);}});
});
相比之下,我们可以利用现代浏览器提供的 Intersection Observer API 来更高效地监测元素的可见性变化。
// 定义一个 Intersection Observer
const observer = new IntersectionObserver(entries => {entries.forEach(entry => {// 如果元素可见if (entry.isIntersecting) {// 执行相应操作console.log(`${entry.target} is visible.`);}});
});// 获取需要监测可视性的元素
const elements = document.querySelectorAll('.target-element');// 监测每个元素
elements.forEach(element => {observer.observe(element);
});
2. 仅渲染可见区域:优化性能
虚拟化列表的另一个关键优化是仅渲染可见区域内的元素,而不是渲染整个列表。这样做可以大大减少渲染所需的时间和资源,提高页面的性能表现。
const Child = ({ data }) => {const [content, setContent] = useState(null);return <div>{content ? content : 'Loading data...'}</div>;
};
3. 动态加载和卸载:保持内存使用最小化
最后,虚拟化列表还可以通过动态加载和卸载元素来保持内存使用最小化。当用户滚动到可视区域时,新的元素被动态加载,而离开可视区域的元素则被卸载,从而减少页面的内存占用。
我们可以利用前面提到的 Intersection Observer API 来实现这一功能。当元素进入视口时,我们加载它;当元素离开视口时,我们卸载它。这样就可以保持页面上始终只有视口内的内容被渲染,从而提高页面的性能和响应速度。
性能对比:传统 Scroll vs Intersection Observer API
以下是传统滚动监听和 Intersection Observer API 的性能对比数据(假设在相同环境和数据集下测试):
| 方法 | 初始渲染时间 | 滚动性能 | 内存使用 |
|---|---|---|---|
| 传统滚动监听 | 300ms | 低 | 高 |
| Intersection Observer API | 150ms | 高 | 低 |
- 初始渲染时间:使用 Intersection Observer API 的初始渲染时间较短,因为只渲染可见区域。
- 滚动性能:传统滚动监听由于频繁的滚动事件触发和位置计算,滚动性能较低;Intersection Observer API 的滚动性能较高,因为它利用了浏览器的优化机制。
- 内存使用:Intersection Observer API 由于仅加载和渲染可见元素,内存使用更低。
性能测试代码分析
以下是一个示例,展示了如何使用 console.time 和 console.timeEnd 来测量性能:
// 测量传统滚动监听的性能
console.time('Scroll');
window.addEventListener('scroll', () => {// 模拟计算每个元素的位置const elements = document.querySelectorAll('.target-element');elements.forEach(element => {const rect = element.getBoundingClientRect();if (rect.top >= 0 && rect.bottom <= window.innerHeight) {// 模拟渲染逻辑}});
});
console.timeEnd('Scroll');// 测量 Intersection Observer API 的性能
console.time('IntersectionObserver');
const observer = new IntersectionObserver(entries => {entries.forEach(entry => {if (entry.isIntersecting) {// 模拟渲染逻辑}});
});
const elements = document.querySelectorAll('.target-element');
elements.forEach(element => observer.observe(element));
console.timeEnd('IntersectionObserver');
注意:传统滚动监听还会涉及计算,但这里只是简单的监听性能统计。
传统的滚动监听方式通过监听 scroll 事件,在每次滚动时计算每个目标元素的位置,并判断其是否在视窗内。这部分代码的执行会阻塞主线程,尤其在滚动频繁的情况下可能导致性能问题,因为需要不断重新计算元素位置。
相比之下,Intersection Observer API 更高效。它可以检测元素是否可见,并在元素进入或退出视窗时触发回调函数,从而实现需要的功能。
性能总结
在性能方面,传统实现方法通常需要通过监听滚动(scroll)事件来计算元素位置。这种方法存在以下问题:
- 性能消耗大:频繁监听滚动事件会导致性能消耗增加,尤其是在大型数据集的情况下。
- 计算复杂度高:需要手动计算每个列表项与视口的交叉情况,逻辑复杂且容易出错。需要花费大量时间和精力来优化和调试这些计算逻辑。
相比之下,Intersection Observer API 的性能更优,具有以下优点:
- 性能开销低:
Intersection Observer API利用浏览器的内部优化机制,减少了不必要的计算和事件触发,从而提高了性能。相比之下,传统的scroll事件监听方式由于密集触发,可能会导致较大的性能问题。 - 多元素监测:
Intersection Observer API允许同时监测多个元素的交叉状态,而不需要为每个元素都绑定事件监听器。这使得在处理复杂布局和交互时更加高效。 - 异步执行:当元素进入或离开交叉状态时,
Intersection Observer会异步执行回调函数,不会阻塞主线程。这有助于保持页面的响应性和流畅性。 - 应用场景广泛:
Intersection Observer API可以应用于多种场景,如懒加载、无限滚动、广告展示与统计、页面元素动画等。这些应用场景通常需要高效地处理元素与视口之间的交互。
综上所述,Intersection Observer API 在处理大型数据集和复杂交互时,相比传统的 scroll 事件监听方式,提供了更高的性能和更灵活的解决方案。
结论
通过本文的介绍,我们了解了虚拟化列表的工作原理和优势,以及如何使用 react-virtualized-list 库来优化渲染性能。
希望本文能对你有所帮助,有所借鉴!大家有什么疑问或者建议,欢迎在评论区一起讨论。
参考资料
- Intersection Observer API
- react-virtualized-list
- 详解 Intersection Observer API ( 交叉观察器 )
相关文章:
性能飙升50%,react-virtualized-list如何优化大数据集滚动渲染
在处理大规模数据集渲染时,前端性能常常面临巨大的挑战。本文将探讨 react-virtualized-list 库如何通过虚拟化技术和 Intersection Observer API,实现前端渲染性能飙升 50% 的突破!除此之外,我们一同探究下该库还支持哪些新的特性…...
颠覆传统:探索Web3对传统计算机模式的冲击
随着Web3技术的崛起,传统计算机模式正面临着前所未有的冲击与挑战。Web3作为下一代互联网的代表,以其去中心化、安全可信的特性,正在颠覆着传统计算机模式的种种假设和局限性。本文将深入探讨Web3对传统计算机模式的冲击,并探索其…...
最适合上班族和宝妈的兼职副业,一天500多,小众副业项目
近年来,地方特色小吃逐渐受到人们的热烈追捧,尤其是在直播的助力下,许多地方的特色小吃得以走进大众视野,吸引了大量流量和人气。因此,有很大一部分商家和创业者看准了这一商机,纷纷投身于地方特色小吃的制…...
HFish蜜罐实践:网络安全防御的主动出击
引言 随着网络攻击手段的不断演进,传统的被动防御策略已难以应对复杂多变的安全威胁。HFish蜜罐作为一种主动防御工具,通过模拟易受攻击的服务,吸引攻击者,不仅能有效捕获攻击行为,还能为安全分析和溯源提供宝贵信息。…...
vue3+three.js给glb模型设置视频贴图
1.在网上下载一个显示屏或者自己画一个,在blender中设置好显示屏的Mesh,UV设置好,这样方便代码中添加纹理贴图。可以让美术在建模软件中,先随机设置一张图片作为纹理,验证UV是否设置好 关于如何 在blender中给模型设置UV贴图百度很多的 // 视频 import * as THREE from…...
SCARA机器人中旋转花键的维护和保养方法!
作为精密传动元件的一种,旋转花键在工作过程中承受了较大的负荷。在自动化设备上运用广泛,如:水平多关节机械手臂(SCARA)、产业用机器人、自动装载机、雷射加工机、搬运装置、机械加工中心的ATC装置等,最适…...
Linux运维-服务器系统配置初始化脚本
方案一 ,是一个简化的Linux服务器初始化脚本 下面这个是一个简化的Linux服务器初始化脚本示例,它包括了更新软件包、安装常用工具、配置网络和安全设置等基本步骤:这个脚本提供了一个基本的初始化配置示例,包括软件更新、安装工具…...
暑期来临,AI智能视频分析方案筑牢防溺水安全屏障
随着夏季暑期的来临,未成年人溺水事故频发。传统的防溺水方式往往依赖于人工巡逻和警示标识的设置,但这种方式存在人力不足、反应速度慢等局限性。近年来,随着视频监控智能分析技术的不断发展,其在夏季防溺水中的应用也日益凸显出…...
【第3章】SpringBoot实战篇之登录接口(含JWT和拦截器)
文章目录 前言一、JWT1. 什么是JWT2. 使用场景3. 结构3.1 Header3.2 Payload3.3 Signature 4. 使用 二、案例1.引入库2.JwtUtils3. UserController14. ArticleController 三、拦截器1. 定义拦截器2. 注册拦截器 四、测试1. 登录2. 无token3. 有token4. 全局配置 总结 前言 前面…...
vue el-table使用、el-popover关闭、el-image大图预览
1、html <el-table :data"list" :header-cell-style"{ background: #F7F8F9 }"><el-table-column type"index" width"100px" label"序号"></el-table-column><el-table-column prop"pic" l…...
星网智云总经理韦炜:低代码与智能制造融合,探索未来制造的无限可能
下文为广西星网智云总经理韦炜的演讲全文: 大家下午好,今天给大家分享一下玉柴的数字化转型过程,以及整个过程中我们会怎样使用低代码。 ﹀ ﹀ ﹀ #玉柴数字化战略 #两个要点 我们的数字化,是在公司的整一个战略转型下去做的。…...
3d模型批量渲图总是会跳怎么办?---模大狮模型网
在进行3D模型批量渲染时,有时会遇到一些问题,其中一个常见的问题就是渲染过程中出现跳帧或者跳图的情况。这不仅会影响到效率,还可能导致输出结果不符合预期。本文将介绍几种解决这一问题的方法,帮助读者更好地应对3D模型批量渲图…...
【距离四六级只剩一个星期!】刘晓艳四级保命班课程笔记(2)(可分享治资料~)
这一节是专门的听力课程,众所周知,咱们刘晓艳刘老师的口语不是特别的突出,当然口才是一流的☝️。 文章目录 听力预判听前预判 听力过程八大出题关键点视听一致同义转换 听完一道题后平时练习精听步骤 听力预判 听前预判 画关键词ÿ…...
Java之Enum枚举类实践
概述 项目中涉及到很多不变的业务变量,因此我们采用了Enum类来定义相关变量,采用Enum的原因 性能高,常量值的地址唯一,可以直接使用 来判断 完全单例,线程安全 项目实践 package com.bierce;/*** 审核流传状态枚举类*/ public enum FlowTypeEnum {START("开始"…...
Apache POI对Excel进行读写操作
1、什么是Apache POI Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。一般情况下,POI 都是用于操作 Excel 文件。 Apache POI 的应用场景&…...
网络安全中攻击溯源方法
目前网络攻击已经成为常见的安全威胁之一,其造成的危害和损失都是不可估量的,因此网络攻击受到了高度重视。而当我们遭遇网络攻击时,攻击溯源是一项非常重要的工作,可以帮助我们迅速发现并应对各类网络攻击行为,那么网…...
软件设计不是CRUD(21):在流式数据处理系统中进行业务抽象落地——需求分析
本文主要介绍如何在数据处理系统中应用业务抽象的设计思想。目前业界流行的数据处理方式是流式处理,主流的流式处理引擎有Apache Spark,Apache Flink等等。本文选择Apache Flink作为实战案例的落地。由于本文主要是讲解设计思想和流式处理引擎相结合的方…...
远控免杀篇
0x00:前言 随着近两年hvv和红蓝对抗以及国家对于网络安全的重视,国内防护水平都蹭蹭上了一个台阶,不管是内部人员的技术水平提高还是防护设备的层层部署,均给了红队人员想要进一步行动设置了障碍。 通过weblogic的cve-2019-2725获…...
基于单片机的超声波倒车雷达设计
摘 要:文 章设计了一种基于单片机的超声波倒车雷达系统,以 AT89C51 型单片机作为控制核心,集距离测量、显示,方位显示和危险报警于一体,以提高驾驶者在倒车泊车时的安全性和舒适性。本设计采用 Keil 软件对系统程序…...
如何增加服务器的高并发
哈喽呀大家好呀,淼淼又来和大家见面啦,随着互联网应用的普及和用户量的不断增加,服务器的高并发性能成为了开发者们面临的一项重要挑战。在处理大量并发请求时,服务器需要具备高效的处理能力和稳定的性能,以确保系统的…...
鸣鸣很忙上市后首份年报:营收662亿同比增长 经调整净利27亿
雷递网 雷建平 3月31日湖南鸣鸣很忙商业连锁股份有限公司(简称:“鸣鸣很忙”,股份代号:1768)今日发布截至2025年12月31日的财报。财报显示,鸣鸣很忙2025年营收为661.7亿元,较上年他同期的393.44…...
MAI-UI-8B入门:Node.js环境配置与自动化测试
MAI-UI-8B入门:Node.js环境配置与自动化测试 1. 开篇:为什么选择MAI-UI-8B进行自动化测试 如果你正在寻找一个能够真正理解图形界面、像真人一样操作应用的自动化测试方案,MAI-UI-8B绝对值得关注。这个由阿里通义实验室开源的GUI智能体模型…...
**发散创新:基于微应用架构的轻量级权限控制实战设计**在现代前端开
发散创新:基于微应用架构的轻量级权限控制实战设计 在现代前端开发中,**微应用(Micro Frontend)*8 已成为构建复杂单页应用(SPA)的标准方案之一。它允许团队独立开发、部署和维护各自的功能模块,…...
pdfsizeopt如何实现PDF文件无损压缩?3大行业案例与高级技巧全解析
pdfsizeopt如何实现PDF文件无损压缩?3大行业案例与高级技巧全解析 【免费下载链接】pdfsizeopt PDF file size optimizer 项目地址: https://gitcode.com/gh_mirrors/pd/pdfsizeopt 在数字化办公环境中,PDF文件已成为信息传递的标准格式ÿ…...
2026年Java面试最常被问的1000道题目及参考答案
Java学到什么程度可以面试工作? 要达到能够面试Java开发工作的水平,需要掌握以下几个方面的知识和技能: 1. 基础扎实:熟悉Java语法、面向对象编程概念、异常处理、I/O流等基础知识。这是所有Java开发者必备的基础,也…...
ESP32 LVGL8.1 —— 消息框进阶:自定义按钮与事件处理实战
1. ESP32与LVGL8.1消息框基础认知 第一次接触ESP32和LVGL8.1的消息框功能时,我完全被它的灵活性震惊了。想象一下,你正在开发一个智能家居控制面板,当用户操作不当或者系统需要确认时,弹出一个美观的对话框是多么自然的事情。这就…...
华为 eNSP 安装全攻略:Windows 11 25H2 完美适配
本教程适用范围 ✅ Windows 7(所有版本)✅ Windows 10(所有版本)✅ Windows 11 23H2 及以下✅ Windows 11 24H2(OS 内部版本 ≥ 26100.3624)✅ Windows 11 25H2❌ Windows 11 24H2(OS 内部版本…...
【以太网帧格式】
以太网帧格式一、顺序二、分析一、顺序 前导码 | 帧开始定界符 | 目的MAC | 源MAC | 类型(长度) | 数据字段 | 帧校验序列FCS3 (以太网帧最小帧长:64 字节,最大帧长:1518 字节。) 二、分析 1…...
【独家首发】基于eBPF+Java Agent+Istio Telemetry V2的零侵入式调试框架(已落地金融级生产环境,QPS>50K场景验证)
第一章:零侵入式调试框架的演进逻辑与金融级落地价值传统调试方式依赖代码埋点、日志增强或代理注入,不仅增加系统耦合度,更在高敏感、强一致性的金融核心系统中引入不可控风险。零侵入式调试框架应运而生——它不修改业务字节码、不依赖特定…...
忍者像素绘卷效果实测:同一Prompt下不同步数对像素锐度影响对比分析
忍者像素绘卷效果实测:同一Prompt下不同步数对像素锐度影响对比分析 1. 测试背景与目的 忍者像素绘卷作为一款基于Z-Image-Turbo深度优化的图像生成工具,其独特的16-Bit复古游戏美学风格吸引了大量创作者。在实际使用中,我们发现"描绘…...
