基于react-virtualized实现多表格:添加跨页宽的头尾区域
Hey there! Let's figure out how to build those repeating header-table-footer sections with react-virtualized for smooth performance, even with lots of groups. Here's a solid approach tailored to your needs:
Core Idea
We'll use react-virtualized's List component to virtualize the entire collection of header-table-footer groups. Each "row" in the List will be a full group (header + virtualized table + footer). This way, only the groups visible in the viewport get rendered, which keeps things fast even with hundreds of groups.
Step-by-Step Implementation
First, make sure you have react-virtualized installed:
npm install react-virtualized
Then, here's the complete code example:
import React from 'react'; import { List, Table, Column, AutoSizer } from 'react-virtualized'; import 'react-virtualized/styles.css'; // Don't forget the default styles! // Component for a single header-table-footer group const TableGroup = ({ groupData }) => { // Define fixed heights for consistency (adjust these to your needs) const HEADER_HEIGHT = 50; const FOOTER_HEIGHT = 50; const ROW_HEIGHT = 40; const TABLE_HEIGHT = groupData.tableRows.length * ROW_HEIGHT; // Helper to fetch table rows const rowGetter = ({ index }) => groupData.tableRows[index]; return ( <div style={{ width: '100%', marginBottom: '12px' }}> {/* Full-width Header */} <div style={{ width: '100%', height: HEADER_HEIGHT, backgroundColor: '#f8f9fa', display: 'flex', alignItems: 'center', padding: '0 16px', fontWeight: 600, borderBottom: '1px solid #e9ecef' }}> {groupData.headerText} </div> {/* Virtualized Table */} <AutoSizer> {({ width }) => ( <Table width={width} height={TABLE_HEIGHT} headerHeight={ROW_HEIGHT} rowHeight={ROW_HEIGHT} rowCount={groupData.tableRows.length} rowGetter={rowGetter} bordered={false} > <Column label="ID" dataKey="id" width={100} /> <Column label="Name" dataKey="name" width={220} /> <Column label="Details" dataKey="details" width={180} /> {/* Add more columns as needed */} </Table> )} </AutoSizer> {/* Full-width Footer */} <div style={{ width: '100%', height: FOOTER_HEIGHT, backgroundColor: '#f8f9fa', display: 'flex', alignItems: 'center', padding: '0 16px', color: '#6c757d', borderTop: '1px solid #e9ecef' }}> {groupData.footerText} </div> </div> ); }; // Parent component to render all virtualized groups const VirtualizedGroupedTables = () => { // Sample data - replace with your actual data const groups = [ { headerText: 'Customer Records', footerText: 'Total: 12 customers', tableRows: Array.from({ length: 12 }, (_, i) => ({ id: i + 1, name: `Customer ${i + 1}`, details: `Tier ${i % 3 + 1}` })) }, { headerText: 'Product Inventory', footerText: 'Total: 18 products', tableRows: Array.from({ length: 18 }, (_, i) => ({ id: i + 1, name: `Product ${i + 1}`, details: `In Stock: ${Math.floor(Math.random() * 100)}` })) }, { headerText: 'Order History', footerText: 'Total: 25 orders', tableRows: Array.from({ length: 25 }, (_, i) => ({ id: i + 1, name: `Order #${i + 1000}`, details: `${Math.floor(Math.random() * 500)}$` })) }, // Add as many groups as you need! ]; // Calculate height for each group in the List const getGroupHeight = ({ index }) => { const group = groups[index]; return 50 + (group.tableRows.length * 40) + 50; // Header + Table Rows + Footer }; // Render each group in the virtualized List const renderGroup = ({ index, key, style }) => ( <div key={key} style={style}> <TableGroup groupData={groups[index]} /> </div> ); return ( <div style={{ height: '90vh', width: '100%', padding: '16px' }}> <AutoSizer> {({ width, height }) => ( <List width={width} height={height} rowCount={groups.length} rowHeight={getGroupHeight} rowRenderer={renderGroup} /> )} </AutoSizer> </div> ); }; export default VirtualizedGroupedTables;
Key Details to Note
- Virtualization Layers: We have two levels of virtualization here:
- The outer
Listvirtualizes the entire header-table-footer groups. - Each inner
Tablevirtualizes its own rows, which is crucial if your tables have lots of data.
- The outer
- Fixed Heights: Using fixed heights for headers, footers, and table rows makes it easy for react-virtualized to calculate scroll positions accurately. If you need variable row heights, you can use
CellMeasurerfrom react-virtualized to dynamically compute them. - Responsiveness:
AutoSizerensures the components fit the available space in their parent container, making the layout responsive. - Styling: The inline styles are just examples—you can replace them with CSS classes or a styling solution of your choice (like styled-components) to match your app's design.
Adjustments for Your Use Case
- If you want tables with internal scrolling (instead of expanding to fit all rows), set a fixed height for the
Table(e.g.,height: 300) instead of calculating it from row count. The group height would then be50 + 300 + 50. - For dynamic content that changes height, you'll need to update the
List's cache or force a re-measure using react-virtualized's API.
内容的提问来源于stack exchange,提问作者Danny Larsen
相关产品推荐
相关产品推荐

