在 React 中渲染大型数据集的 3 种方法

随着 Web 应用程序变得越来越复杂,我们需要找到有效的方法来优化性能和渲染大型数据集。在 React 应用程序中处理大型数据集时,一次呈现所有数据可能会导致性能不佳和加载时间变慢。

虚拟化是一种通过一次仅呈现数据集的一部分来解决此问题的技术,从而为用户提供更快、更流畅的体验。在本文中,我们将探讨和比较可用于 React 的各种虚拟化列表库的优缺点,包括:

  • React Virtuoso

  • React Window

  • react-infinite-scroller

React Virtuoso

React Virtuoso 是 React 的虚拟化列表库,可以快速高效地渲染大型数据集。它是高度可定制的,我们可以使用它来渲染简单和复杂的数据结构。

React Virtuoso 使用窗口技术,仅渲染屏幕上可见的元素,从而缩短加载时间和提高性能。

下面介绍如何通过两个步骤在您的应用程序中使用 React Virtuoso

首先,安装 Virtuoso 库:

npm install react-virtuoso

接下来,在应用程序中使用该组件:

import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { Virtuoso } from 'react-virtuoso'
const App = () => (<Virtuosostyle={{ height: '600px',background: '#f8f8f8'}}totalCount={10000}itemContent={index => (<div style={{ background: index % 2 === 0 ? '#ffbb00' : '#ffcc33',color: '#333',padding: '10px',fontSize: '16px',fontFamily: 'Arial, sans-serif',border: '1px solid #ccc',borderRadius: '4px',margin: '5px 0'}}>Item {index}</div>)}/>
)
export default App;
ReactDOM.render(<App />, document.getElementById('root'))

在上面的代码中,我们从 react-virtuoso 库中导入 Virtuoso 组件。

接下来,我们定义一个名为 返回 App 组件的功能 Virtuoso 组件。

该 Virtuoso 组件包含多个道具:

  • style :设置组件的样式,包括其高度和背景颜色

  • totalCount :设置列表中的项目总数;在这种情况下,10,000

  • itemContent :接收一个 index 参数并返回用于在该索引处呈现项目的 JSX 代码

在这种情况下,该函数呈现一个 div 包含文本“Item”的元素,后跟索引号。该 prop 根据 style 索引是奇数还是偶数来设置 div 元素的背景颜色、字体大小、字体系列、边框、边框半径和边距。

下面是我们代码的结果:

图片

我们也可以将图像添加到列表中:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Virtuoso } from 'react-virtuoso';
const App = () => {const [images, setImages] = React.useState([]);// Fetch random images from Unsplash on component mountReact.useEffect(() => {const fetchImages = async () => {const response = await fetch('https://api.unsplash.com/photos/random?count=100',{headers: {Authorization: 'Client-ID <UNSPLASH ACCESS KEY>',},});const data = await response.json();const urls = data.map(item => item.urls.thumb);setImages(urls);};fetchImages();}, []);return (<Virtuosostyle={{ height: '400px',background: '#f8f8f8'}}totalCount={10000}itemContent={index => (<div style={{ background: index % 2 === 0 ? '#ffbb00' : '#ffcc33',color: '#333',padding: '10px',fontSize: '16px',fontFamily: 'Arial, sans-serif',border: '1px solid #ccc',borderRadius: '4px',margin: '5px 0',display: 'flex',alignItems: 'center'}}><img src={images[index % 100]} alt={`Item ${index}`} style={{ marginRight: '10px', width: '50px', height: '50px', borderRadius: '50%' }} />Item {index}</div>)}/>);
};
export default App;
ReactDOM.render(<App />, document.getElementById('root'));

您可能会注意到,此代码与我们以前的代码没有太大区别。我们使用 useState 和useEffect钩子定义一个功能组件 App 。然后,我们声明一个调用 images 的状态变量,并使用 Hook  useState 将其初始值设置为空数组。

我们定义了一个调用 fetchImages 的函数,该函数使用 API 向 Unsplash fetch API 发出 GET 请求以检索 100 张随机图像。然后,我们映射响应数据并提取每个图像的 thumb URL,并使用函数 setImages 将 images 状态变量设置为生成的 URL 数组。

接下来,我们使用 Hook 在 useEffect 组件挂载时调用该 fetchImages 函数一次,因为我们只想获取一次图像。像以前一样,我们返回一个 Virtuoso 组件,该组件包含以下 props

  • style:设置为为我们的 Virtuoso 组件创建背景颜色和高度, height 其属性为 和 400px 背景属性 #f8f8f8

  • totalCount

  • itemContent

这一次,我们从 itemContent 函数返回的 JSX 代码是一个 div 包含元素 img 和一些文本的元素。元素 img  的src属性设置为与当前 index 值对应的图像的 URL,该 URL 使用取模运算符 ( ) 从 images 状态变量中检索。

图片

Virtuoso 的优点

  • Virtuoso在渲染大型数据集方面非常有效

  • 它是高度可定制的

  • 它提供对动态项目大小的支持

  • 好的性能表现

Virtuoso 的缺点

  • 有限的文档

  • 不支持嵌套列表

React Window

我们要看的下一个库是 React Window,这是一个用于 React 的虚拟化列表库,它使用与 React Virtuoso 相同的窗口技术。

React Window 是 React Virtualized 的更新版本。它还具有高性能,可用于高效渲染大型数据集。React Window 为我们提供了一组 API,我们可以使用它们来自定义列表的行为,使其成为一个灵活而强大的工具。

安装React Window 

npm install --save react-window

为了演示它是如何工作的,我们将使用 Faker 库来生成大型数据集。Faker 是一个生成虚假数据的库,例如姓名、地址和电话号码。

使用 npm 安装伪造程序库:

npm install faker

然后在代码中实现它:

import React from 'react';
import { FixedSizeList } from 'react-window';
import { faker } from '@faker-js/faker';
const App = () => {const data = Array.from({ length: 10000 }).map(() => ({name: faker.name.firstName(),email: faker.internet.email(),}));const Row = ({ index, style }) => {const isEvenRow = index % 2 === 0;const backgroundColor = isEvenRow ? '#F9A03F' : '#FDDB3A';const textColor = isEvenRow ? '#FFFFFF' : '#4A4A4A';const rowStyle = {...style,backgroundColor,color: textColor,display: 'flex',justifyContent: 'space-between',alignItems: 'center',padding: '0 16px',};return (<div style={rowStyle}><p>{data[index].name}</p><p>{data[index].email}</p></div>);};return (<FixedSizeList height={600} width={1200} itemSize={50} itemCount={data.length}>{Row}</FixedSizeList>);
};
export default App;

我们从 react-window 库中导入 FixedSizeList 组件,以及用于生成 faker 用于测试目的的假数据的库。

导入必要的库后,我们定义一个名为的功能组件,该组件 App 创建一个包含 10,000 个对象的数组。每个对象都包含一个 name 和一个email属性;它们的值是使用 faker 库生成的。

接下来,我们定义一个名为 Row 的新功能组件,它接受 index 和 style prop 并呈现每一行数据。它从我们之前定义的 data 数组中检索相应索引的 name 和email 数据,并使用传入 style 的prop将其呈现在 div 元素中。

最后,我们从 react-window 库中返回一个 FixedSizeList 组件,该组件包含以下内容:

  • height 和 width 道具,决定列表的大小

  • itemSize:用于设置每行的高度

  • itemCount:用于设置列表中的项目总数

  • 一个呈现每行数据的函数,该函数设置为我们之前定义的 Row 组件

图片

我们可以使用以下 VariableSizedList 组件创建可变大小的列表:

import React from 'react';
import { VariableSizeList } from 'react-window';
import { faker } from '@faker-js/faker';
const App = () => {const data = Array.from({ length: 10000 }).map(() => ({name: faker.name.firstName(),email: faker.internet.email(),}));const Row = ({ index, style }) => {const isEvenRow = index % 2 === 0;const backgroundColor = isEvenRow ? '#F9A03F' : '#FDDB3A';const textColor = isEvenRow ? '#FFFFFF' : '#4A4A4A';const rowStyle = {...style,backgroundColor,color: textColor,display: 'flex',justifyContent: 'space-between',alignItems: 'center',padding: '0 16px',};return (<div style={rowStyle}><p>{data[index].name}</p><p>{data[index].email}</p></div>);};const getItemSize = index => {const randomHeight = Math.floor(Math.random() * 100) + 50;return randomHeight;};return (<VariableSizeList height={600} width={1200} itemCount={data.length} itemSize={getItemSize}>{Row}</VariableSizeList>);
};
export default App;

图片

在此示例中,该 getItemSize 函数计算每行 50–150 像素之间的随机高度。您可以调整计算以生成不同的大小范围,甚至可以根据每行中的数据生成不同的大小。

请注意,由于行高变化非常大,滚动性能可能会受到影响,因为列表组件必须在滚动时计算和定位每一行。

React Window的优点

  • 高性能

  • 定制

  • 支持动态项目大小

  • 良好的文档

React Window的缺点

  • 对嵌套列表的支持有限

  • 没有对滚动恢复的内置支持

react-infinite-scroller

react-infinite-scroller 是一个库,允许您以高性能方式呈现大型数据集。该库还使用窗口化或虚拟化技术,其中仅呈现数据的可见部分,其余部分在用户滚动时按需加载。

我们也将使用 Faker 库来生成大型数据集。安装它:

npm install faker

然后安装 react-infinite-scroller :

npm i react-infinite-scroller

接下来,我们将创建一个名为的组件 UserList ,该组件呈现由Faker库生成的用户列表。

import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import { faker } from "@faker-js/faker";
function UserList() {const [users, setUsers] = useState([]);const loadMore = (page) => {const newUsers = [];for (let i = 0; i < 20; i++) {newUsers.push({name: faker.name.findName(),email: faker.internet.email(),phone: faker.phone.phoneNumber(),});}setUsers([...users, ...newUsers]);};const rowStyle = {display: "flex",justifyContent: "space-between",alignItems: "center",padding: "10px",backgroundColor: "#f1f1f1",borderBottom: "1px solid #ccc",fontSize: "16px",color: "#333",};const nameStyle = {fontWeight: "bold",color: "#38a3a5",};const emailStyle = {fontStyle: "italic",color: "#ff7f50",};const phoneStyle = {color: "#6a5acd",};return (<InfiniteScrollpageStart={0}loadMore={loadMore}hasMore={true}loader={<div className="loader" key={0}>Loading ...</div>}><ul style={{ listStyle: "none", margin: "0", padding: "0" }}>{users.map((user, index) => (<li key={index} style={rowStyle}><div style={nameStyle}>{user.name}</div><div style={emailStyle}>{user.email}</div><div style={phoneStyle}>{user.phone}</div></li>))}</ul></InfiniteScroll>);
}
export default UserList;

图片

让我们分解一下。在组件中 UserList ,我们使用 useState Hook 来管理 users 数组的状态。该loadMore函数生成 20 个新用户并将其追加到现有 users 数组中。

装载组件时,将呈现 InfiniteScroll 组件。 pageStart prop 指示将从何处加载数据的页码。

loadMore prop 是一个回调函数,当用户滚动到列表末尾时调用。它接收页码作为参数,可用于从服务器加载数据。在我们的例子中,我们使用Faker库生成虚假数据。

hasMore prop 指示是否有更多数据要加载。在我们的例子中,我们希望将其设置为 true ,因为我们想无限期地加载更多数据。 loader prop 是一个 React 元素,在加载数据时呈现。我们添加了一个简单的加载器,用于显示加载消息。

最后,我们使用该方法map呈现用户列表。每个用户都呈现在一个 li 元素中,并显示每个用户的姓名、电子邮件和电话号码。

对于样式,我们使用 JavaScript 对象定义几种样式,并使用 style 属性将它们应用于相应的元素。该 rowStyle 对象应用浅灰色背景色,具有深灰色边框和白色文本颜色,而 nameStyle 、 emailStyle 和对象分别为姓名、电子邮件和电话号码字段定义不同的文本颜色和 phoneStyle 样式。

使用 react-infinite-scroller 的优点

  • 改进的性能:使用反应无限滚动器的主要优点是其改进的性能。通过仅渲染数据的可见部分,它减少了 DOM 节点的数量,从而提高了渲染速度

  • 减少内存消耗:由于仅呈现数据的可见部分,因此显着减少了内存消耗

  • 无限滚动:库提供开箱即用的无限滚动,这意味着数据可以动态加载,无需页面刷新或手动加载

  • 易于使用:React-infinite-scroller 易于使用,并与 React 应用程序无缝集成

使用 react-infinite-scroller 缺点

  • 复杂的实现:实现无限滚动可能很复杂,特别是对于初学者。您需要确保以高性能方式加载数据,同时跟踪组件的状态

  • 动态高度问题:反应无限滚动器不能解决动态高度问题。如果列表中的项目具有不同的高度,则库无法准确计算整个列表的高度,从而导致滚动位置不正确

功能集比较表

功能/工具React VirtuosoReact Windowreact-infinite-scroller
性能非常好非常好
API丰富有限有限
虚拟化支持YesYesYes
SSR渲染支持YesYesNo
自定制有限有限
易于使用容易容易容易
面向开发人员的内置功能提供分页和无限加载功能。开发者社区实现了带有Chrome和Firefox扩展的开发者工具GUI。支持将缓存持久化到外部存储位置(即本地存储)。提供分页和无限加载功能。它带有一个官方的开发人员工具GUI,支持缓存操作。支持将缓存持久化到外部存储位置(即本地存储)。N/A
React suspense支持支持N/A
对其他前端库的官方支持否,类似的社区库可用:sswr在进行中,类似的社区库可用:vue-queryN/A

总结

高效渲染大型数据集是 Web 开发的一个关键方面。虚拟化是一种使开发人员能够有效地呈现大型数据集并提高 Web 应用程序性能的技术。

在本文中,我们探讨了可用于 React 的各种虚拟化列表库,包括 React VirtuosoReact Window 和 react-infinite-scroll。每个库都有其优点和缺点,库的选择取决于特定的用例。通过使用这些虚拟化列表库,您可以显著提高 React应用程序的性能并提供更流畅的用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1. C++面向过程

一、C简介 1.1 C的产生及其特点 从C语言发展演变而来&#xff0c;解决了C语言中存在的一些问题&#xff0c;并增加了对面向对象程序设计方法的支持 与其他高级语言相比&#xff0c;C语言可以直接访问物理地址&#xff1b;与汇编相比它具有良好的可读性和可移植性 C于1980年由…

【MySQL】使用C/C++连接MySQL数据库

【MySQL】使用C/C连接MySQL数据库 验证使用select特殊点 本文目的&#xff1a;使用MySQL提供的CAPI完成对数据库的操作 验证 #include <iostream> #include <mysql/mysql.h>int main() {std::cout<<"mysql cilent version: "<<mysql_get_cl…

uniapp h5支付宝支付后端返回Form表单,前端如何处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1.调取接口拿到后端返回的form表单 前言 uniapp h5 支付宝支付&#xff0c;后端返回一串form表单&#xff0c;前端如何拿到支付串并且调用支付 1.调取接口拿到…

面试热题(接雨水问题)

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 我们看到题的第一步&#xff0c;永远是对入参进行判断 public int trap(int[] height) {if (height null) {return 0;}...} 但是我们想想看&#xff0c;接…

【数据结构】单链表

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、什么是链表 1.1链表的概念及结构 1.2单链表的结构 二、链表的实现 …

macOS install redis遇到的bug(tar包,homebrew安装,守护进程redis.conf配置)

官网下载tar包再make install 首先是sudo make test的时候一直报 !!! WARNING The following tests failed: *** [err]: trim on SET with big value in tests/unit/type/string.tcl Expected [r memory usage key] < 42000 (context: type source line 478 file /usr/loca…

Qt项目---简单的计算器

在这篇技术博客中&#xff0c;我们将介绍如何使用Qt框架实现一个简单的计算器应用。我们将使用C编程语言和Qt的图形用户界面库来开发这个应用&#xff0c;并展示如何实现基本的算术操作。 项目设置 首先&#xff0c;我们需要在Qt Creator中创建一个新的Qt Widgets应用程序项目…

使用 github 同步谷歌浏览器书签

想必使用谷歌浏览器Chrome的用户一定非常头疼的一件事就是&#xff1a;账户不能登录&#xff0c;书签收藏夹不能同步&#xff0c;换一台电脑书签收藏夹没有了&#xff01; 下面教大家一招亲测有效适用的方法解决书签同步问题&#xff0c;在任何电脑都可以同步了 1、去下载谷歌…

【Linux】——线程安全

目录 关于线程进程的问题 可重入与线程安全 常见的线程安全的情况 常见的不可重入的情况 常见的可重入的情况 可重入与线程安全区别 可重入与线程安全联系 Linux线程互斥 进程线程间的互斥相关概念 互斥量mutex 互斥量mutex常用接口 互斥量改造抢票系统 互斥量的原…

Zookeeper基础操作

搭建Zookeeper服务器 windows下部署 下载地址: https://mirrors.cloud.tencent.com/apache/zookeeper/zookeeper-3.7.1/ 修改配置文件 打开conf目录&#xff0c;将 zoo_sample.cfg复制一份&#xff0c;命名为 zoo.cfg打开 zoo.cfg&#xff0c;修改 dataDir路径&#xff0c…

leetcode 452. 用最少数量的箭引爆气球

2023.8.2 本题思路先将二维数组points按照第一个维度排序&#xff0c; 然后初始化射箭数为1&#xff0c;因为题中提示说了最少有一个气球。 在遍历这些气球&#xff0c;看是否有重叠&#xff0c;如果没有重叠区域&#xff0c;射箭数&#xff1b;如果有重叠区域&#xff0c;更新…

java快速生成数据库表文档(HTML、DOC、MD)

在企业级开发中、我们经常会有编写数据库表结构文档的时间付出&#xff0c;关于数据库表结构文档状态&#xff1a;要么没有、要么有、但都是手写、后期运维开发&#xff0c;需要手动进行维护到文档中&#xff0c;很是繁琐&#xff0c;这里推荐一个开源项目&#xff1a;screw gi…

Spring源码面试题

Spring源码面试题 谈谈你对Spring框架的理解? Spring 是一个开源的应用程序框架&#xff0c;它起源于 Rod Johnson 在其著名的 Spring Framework 专著中提出的一个轻量级框架的观念。下面是 Spring 的发展历史&#xff1a; 2002 年&#xff0c;Rod Johnson 发表了他的专著 …

RISC-V 指令集介绍

1. 背景介绍 指令集从本质上可以分为复杂指令集&#xff08;Complex Instruction Set Computer&#xff0c;CISC&#xff09;和精简指令集&#xff08;Reduced Instruction Set Computer&#xff0c;RISC&#xff09;两种。复杂指令集的特点是能够在一条指令内完成很多事情。 指…

云安全攻防(四)之 云原生技术

云原生技术 容器技术 容器与虚拟化 虚拟化&#xff08;Virtualization&#xff09;和容器&#xff08;Container&#xff09;都是系统虚拟化的实现技术&#xff0c;可实现系统资源的”一虚多“共享。容器技术可以理解成一种”轻量的虚拟化“方式&#xff0c;此处的”轻量“主…

安全加固服务器

根据以下的内容来加固一台Linux服务器的安全。 首先是限制连续密码错误的登录次数&#xff0c;由于RHEL8之后都不再使用pam_tally.so和pam_tally2.so&#xff0c;而是pam_faillock.so 首先进入/usr/lib64/security/中查看有什么模块&#xff0c;确认有pam_faillock.so 因为只…

UG\NX 二次开发 相切面、相邻面的选择控件

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan 简介&#xff1a; 有群友问“UFUN多选功能过滤面不能选择相切面或相邻面之类的吗&#xff1f;” 这个用Block UI的"面收集器"就可以&#xff0c;ufun函数是不行的。 效果&am…

Debeizum 增量快照

在Debeizum1.6版本发布之后&#xff0c;成功推出了Incremental Snapshot&#xff08;增量快照&#xff09;的功能&#xff0c;同时取代了原有的实验性的Parallel Snapshot&#xff08;并行快照&#xff09;。在本篇博客中&#xff0c;我将介绍全新快照方式的原理&#xff0c;以…

HTML+CSS+JavaScript:实现B站评论发布效果

一、需求 1、用户输入内容&#xff0c;输入框左下角实时显示输入字数 2、为避免用户输入时在内容左右两端误按多余的空格&#xff0c;在发送评论时&#xff0c;检测用户输入的内容左右两端是否带有空格&#xff0c;若有空格&#xff0c;发布时自动取消左右两端的空格 3、若用…

浏览器的同源策略 - 跨域问题

1.什么是跨域 跨域问题的实质是浏览器的同源策略造成的。浏览器同源策略是浏览器为 JavaScript 施加的限制。简单点说就是非同源会出现如下等限制&#xff1a; 无法访问其他源下的网页的 Cookies&#xff0c;Storage等&#xff1b;无法访问其他源下的DOM对象和 JS 对象;无法使…