如何在 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 次瀏覽

啟動你的 職業生涯

透過完成課程獲得認證

開始
廣告

© . All rights reserved.