使用React-Window實現(xiàn)虛擬滾動效果的示例代碼
1. 了解 React-Window
React-Window 是一個為 React 應(yīng)用程序中高效渲染大數(shù)據(jù)集而設(shè)計的庫。它基于窗口化或虛擬化的原則運行,這對于提高數(shù)據(jù)量大的 Web 應(yīng)用程序的性能至關(guān)重要。
2. React-Window 原理
- 窗口化: React-Window 僅渲染用戶可視區(qū)域中當前可見的元素。這最小化了 DOM 元素的數(shù)量,減少內(nèi)存使用并提升性能。
- DOM 元素的可重用性: 用戶滾動時,React-Window 重用現(xiàn)有的 DOM 元素來展示新項,進一步提升性能。
- 簡化的 API: 相比于 React-Virtualized,它提供了更簡單、更流暢的 API,使用起來更容易,同時功能強大。
3. 安裝
通過 npm 安裝 React-Window:
npm install react-window
4. 基本使用
一個基本的列表實現(xiàn):
import { FixedSizeList as List } from 'react-window'; const MyList = () => ( <List height={150} itemCount={1000} itemSize={35} width={300} > {({ index, style }) => <div style={style}>Item {index}</div>} </List> );
5. 高級使用案例和示例
5.1 自定義項目渲染器
自定義列表或網(wǎng)格中每個項目的渲染方式。
import { FixedSizeList as List } from 'react-window'; // 偶數(shù)和奇數(shù)項組件 const EvenItem = ({ index }) => <div>Even: Item {index}</div>; const OddItem = ({ index }) => <div>Odd: Item {index}</div>; const MyCustomItem = ({ index, style }) => ( <div style={style}> {index % 2 === 0 ? <EvenItem index={index} /> : <OddItem index={index} />} </div> ); const MyList = () => ( <List height={150} itemCount={1000} itemSize={35} width={300} > {MyCustomItem} </List> );
5.2 動態(tài)加載
結(jié)合數(shù)據(jù)獲取實現(xiàn)用戶滾動時動態(tài)加載和渲染數(shù)據(jù)。
import { InfiniteLoader, List } from "react-window-infinite-loader"; const loadMoreItems = /* 加載更多項目的函數(shù) */ <InfiniteLoader isItemLoaded={/* 檢查項目是否加載的函數(shù) */} itemCount={1000} loadMoreItems={loadMoreItems} > {({ onItemsRendered, ref }) => ( <List onItemsRendered={onItemsRendered} ref={ref} {/* 其他屬性 */} > {/* 項目渲染器 */} </List> )} </InfiniteLoader>
有關(guān)此示例的更多詳細信息,請查看下一章節(jié)。
5.3 性能優(yōu)化
演示減少渲染 DOM 元素的數(shù)量。
// 使用相同的 FixedSizeList 示例,但使用大量數(shù)據(jù)集 <List height={150} itemCount={100000} itemSize={35} width={300} > {({ index, style }) => <div style={style}>Item {index}</div>} </List>
6. 詳細實現(xiàn)動態(tài)加載
為了展示如何在使用 Express 構(gòu)建的后端中與 React-Window 結(jié)合實現(xiàn)動態(tài)加載,我們創(chuàng)建一個示例,前端從后端獲取數(shù)據(jù),用戶通過列表滾動時請求更多數(shù)據(jù)。后端將提供分頁數(shù)據(jù),前端在達到當前加載項的末尾時請求更多數(shù)據(jù)。
使用 Express 的后端設(shè)置
創(chuàng)建一個簡單的 Express 服務(wù)器:
首先,建立一個能夠提供分頁數(shù)據(jù)的 Express 服務(wù)器。
express = require('express'); const app = express(); const cors = require('cors'); const PORT = 3000; app.use(cors()); // 模擬數(shù)據(jù)數(shù)組 const data = new Array(1000).fill(null).map((_, index) => ({ id: index, name: `Item ${index}` })); // 獲取分頁數(shù)據(jù)的端點 app.get('/data', (req, res) => { const { page = 1, limit = 50 } = req.query; console.log('req.query:', req.query) const startIndex = (page - 1) * limit; const endIndex = page * limit; res.json({ data: data.slice(startIndex, endIndex), total: data.length }); }); app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
在這個設(shè)置中,創(chuàng)建了一個模擬數(shù)據(jù)數(shù)組,/data
端點根據(jù)請求的頁碼和限制提供部分數(shù)據(jù)。
使用 React-Window 和無限加載的前端設(shè)置
在前端實現(xiàn)無限加載:
使用 React 和 React-Window 實現(xiàn)無限加載特性。
import React, { useState, useEffect } from 'react'; import { FixedSizeList as List } from 'react-window'; import axios from 'axios'; const ROW_HEIGHT = 35; function InfiniteLoadingList() { const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const loadMoreItems = async () => { const { data } = await axios.get(`http://localhost:3000/data?page=${page}&limit=50`); setItems(prev => [...prev, ...data.data]); setTotal(data.total); setPage(prev => prev + 1); }; useEffect(() => { loadMoreItems(); }, []); useEffect(() => { console.log('items', items); }, [items]); const isItemLoaded = index => index < items.length; const renderItem = ({ index, style }) => ( <div style={style}> {isItemLoaded(index) ? items[index].name : 'Loading...'} </div> ); return ( <List height={400} itemCount={total} itemSize={ROW_HEIGHT} width={300} onItemsRendered={({ visibleStopIndex }) => { console.log('visibleStopIndex:', visibleStopIndex) if (!isItemLoaded(visibleStopIndex) && items.length < total) { loadMoreItems(); } }} > {renderItem} </List> ); } export default InfiniteLoadingList;
在這個 React 組件中,使用 useState
和 useEffect
管理列表的狀態(tài),并在用戶滾動到已加載項目末尾附近時獲取新數(shù)據(jù)。FixedSizeList
的 onItemsRendered
函數(shù)檢查是否需要加載新數(shù)據(jù)。
總結(jié)
這個設(shè)置展示了在 React 應(yīng)用程序中使用 React-Window 實現(xiàn)基本的動態(tài)加載和使用 Express 后端提供分頁數(shù)據(jù)的簡單實現(xiàn)。它有效地展示了如何通過根據(jù)需要逐步加載數(shù)據(jù)來處理大型數(shù)據(jù)集,改善性能和用戶體驗。
7. 結(jié)論
React-Window 對于解決 React 應(yīng)用程序中渲染大型數(shù)據(jù)集相關(guān)的性能問題起著關(guān)鍵作用。它對虛擬化的方法,結(jié)合簡化的 API,使其成為開發(fā)者的首選。通過僅渲染可見內(nèi)容并高效地重用 DOM 元素,React-Window 確保即使在數(shù)據(jù)量龐大的情況下,應(yīng)用程序也能保持響應(yīng)性和性能。
到此這篇關(guān)于使用React-Window實現(xiàn)虛擬滾動效果的示例代碼的文章就介紹到這了,更多相關(guān)React虛擬滾動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript的React框架中的JSX語法學(xué)習(xí)入門教程
這篇文章主要介紹了JavaScript的React框架中的JSX語法學(xué)習(xí)入門教程,React是由Facebook開發(fā)并開源的高人氣js框架,需要的朋友可以參考下2016-03-03再次談?wù)揜eact.js實現(xiàn)原生js拖拽效果引起的一系列問題
React 起源于 Facebook 的內(nèi)部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設(shè) Instagram 的網(wǎng)站.本文給大家介紹React.js實現(xiàn)原生js拖拽效果,需要的朋友一起學(xué)習(xí)吧2016-04-04react+antd實現(xiàn)動態(tài)編輯表格數(shù)據(jù)
這篇文章主要為大家詳細介紹了react+antd實現(xiàn)動態(tài)編輯表格數(shù)據(jù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08