如何在 Material UI 的自动完成组件中使用虚拟列表?
显示数据列表是 Web 应用程序的常见需求。或者带有可滚动标题的表格。您很可能已经无数次地执行过它。但是,如果您必须同时显示数千行数据会怎样?
在本文中,我们将了解如何使用 Material UI 的自动完成组件的虚拟列表来生成具有大型数据集的流畅用户界面。流行的 React UI 框架 Material UI 提供了大量具有尖端设计和一流性能的组件。在处理自动完成组件中的大型数据集时,传统的渲染技术可能会导致性能问题,因此为了防止这些问题,我们将使用 react-virtualized 来有效地显示大量数据。
了解虚拟列表
虚拟列表,也称为无限滚动,是一种更有效地渲染长列表的方法,方法是仅显示屏幕上可见的项目。虚拟列表根据用户的视口渲染较小的项目子集,而不是渲染整个数据集,从而导致加载时间更快,滚动更流畅。
为什么要使用 react-virtualized?
经常使用 React 的开发人员会渲染包含多行的列表并使用 map 函数。即使滚动条通常会隐藏溢出的内容,但如果他们使用该方法渲染数千行,Web 浏览器仍会始终生成数千个 DOM 元素。当用户事件(如滚动)导致 DOM 元素位置发生变化时,渲染新的 DOM 元素需要物理内存并使用 CPU 和 GPU 硬件。
一种性能友好的渲染大型列表的方法是使用像 react-virtualized 这样的库,它使用虚拟渲染来一次渲染大量元素的列表。为了最大程度地减少对应用程序的性能影响,此库通常仅渲染长列表中可见的行并生成更少的 DOM 元素。换句话说,此库仅显示必要的行,同时使用 CSS 样式虚拟指示隐藏行的存在。
在自动完成中使用虚拟列表的步骤
步骤 1:创建 React 应用程序
第一步是创建一个新的 react 应用程序(如果尚未创建)。我们将使用传统方法,即 create-react-app。
npx create-react-app myproject cd myproject
步骤 2:安装和导入 Material UI
创建 react 应用程序后,让我们首先安装 material ui 及其依赖项,然后导入它。
npm install @mui/material @emotion/react @emotion/styled // Importing the autocomplete virtualized import React from 'react'; import AutocompleteVirtualized from '@mui/lab/AutocompleteVirtualized'; import TextField from '@mui/material/TextField';
步骤 3:创建虚拟数据集
要使用虚拟列表,我们必须首先创建一个数据集。因此,现在我们将使用数组来创建虚拟数据集。稍后我们还将了解如何使用动态 API 数据列表。
const dataset = Array.from({ length: 500 }, (_, index) => ({ title: `Option ${index + 1}`, val: index + 1, }));
在这里,我们创建了一个包含 500 个虚拟数据集的列表,其中 title 和 val 是数据集的选项。
步骤 4:在自动完成中定义虚拟列表
现在,我们已经创建了自己的虚拟数据集,让我们将其集成到虚拟化的自动完成中。以下是使用它们的语法:
const CustomVirtualComponent = () => { return ( <AutocompleteVirtualized options={dataset} getOptionLabel={(item) => item.title} renderInput={(params) => <TextField {...params} label="Add label" />} /> ); };
示例
在此示例中,我们使用数组函数创建了一个虚拟数据集,该函数生成大约 400 个项目的随机列表,其标签和 val 作为其选项。然后,使用我们使用 react-window 的 VariableSizeList 创建的自定义 ListboxComponent 有效地渲染这些项目,并且仅在必要时渲染列表以获得最佳性能,即使选项数量很大也是如此。
import React, { useState } from "react"; import Autocomplete from "@mui/material/Autocomplete"; import TextField from "@mui/material/TextField"; import { VariableSizeList } from "react-window"; const virtualDataSet = () => { const arrayOfData = []; for (let j = 0; j < 400; j++) { arrayOfData.push({ title: `Random ${j}`, val: j, }); } return arrayOfData; }; const dataset = virtualDataSet(); const ItemListComponent = React.forwardRef(function ListboxComponent( { children, ...other }, ref ) { const getItemSize = (index) => { return 35; }; const itCount = Array.isArray(children) ? children.length : 0; return ( <div ref={ref}> <VariableSizeList height={itCount * 35} itemSize={getItemSize} itemCount={itCount} overscanCount={10} {...other}> {({ index, style }) => <div style={style}>{children[index]}</div>} </VariableSizeList> </div> ); }); export default function App() { const [ipVal, setIpVal] = useState(""); const handleVal = (event, value) => { setIpVal(value); }; return ( <div style={{ display: "flex", marginTop: 30, flexDirection: "column", alignItems: "center", justifyContent: "center", }}> <h3>Select a option</h3> <Autocomplete options={dataset} inputValue={ipVal} sx={{ width: "70%" }} getOptionLabel={(item) => item.title} ListboxComponent={ItemListComponent} onInputChange={handleVal} renderInput={(params) => ( <TextField {...params} label="select option from virtual list" variant="standard" /> )} /> </div> ); }
输出
示例
在此示例中,我们利用数组函数创建了一个数据集,该数据集生成大约 400 个项目的列表。这些项目以标签和 val 作为其选项。为了增强吸引力,我们在自动完成组件中合并了背景颜色和样式。这些项目的渲染由我们使用 react 窗口 VariableSizeList 开发的自定义 ListboxComponent 高效处理。即使处理大量选项,这也确保了性能,因为渲染了必要的项目。
import React, { useState } from "react"; import Autocomplete from "@mui/material/Autocomplete"; import TextField from "@mui/material/TextField"; import { VariableSizeList } from "react-window"; import { Chip } from "@mui/material"; const virtualDataSet = () => { const arrayOfData = []; for (let j = 0; j < 400; j++) { arrayOfData.push({ title: `Random ${j}`, val: j, }); } return arrayOfData; }; const dataset = virtualDataSet(); const ItemListComponent = React.forwardRef(function ListboxComponent( { children, ...other }, ref ) { const getItemSize = (index) => { return 35; }; const itCount = Array.isArray(children) ? children.length : 0; return ( <div ref={ref}> <VariableSizeList height={itCount * 35} itemSize={getItemSize} itemCount={itCount} overscanCount={10} {...other} > {({ index, style }) => <div style={style}>{children[index]}</div>} </VariableSizeList> </div> ); } ); export default function App() { const [ipVal, setIpVal] = useState(""); const handleVal = (event, value) => { setIpVal(value); }; return ( <div style={{ display: "flex", marginTop: 30, flexDirection: "column", alignItems: "center", justifyContent: "center", }}> <h3>Select a option</h3> <Autocomplete options={dataset} inputValue={ipVal} sx={{ width: "70%", backgroundColor: "lightgreen", padding: 3, borderRadius: 5 }} getOptionLabel={(item) => item.title} ListboxComponent={ItemListComponent} onInputChange={handleVal} renderInput={(params) => ( <TextField sx={{backgroundColor: 'green'}} {...params} label="select option from virtual list" variant="standard" /> )} /> </div> ); }
输出
结论
在本文中,我们探讨了如何使用 React 在 Material UI 组件中实现列表。我们集成了 react 窗口等库以启用虚拟化。这种方法使我们能够有效地处理数据集,同时保持快速的加载时间并提供用户体验。通过虚拟化优化渲染和性能,自动完成组件在处理大量数据时提供了可用性。