如何在 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 窗口等库以启用虚拟化。这种方法使我们能够有效地处理数据集,同时保持快速的加载时间并提供用户体验。通过虚拟化优化渲染和性能,自动完成组件在处理大量数据时提供了可用性。

更新于: 2023 年 10 月 30 日

637 次浏览

启动你的 职业生涯

通过完成课程获得认证

开始
广告