如何在Material UI DataGrid排序时固定汇总行至底部
解决Material UI DataGrid汇总行固定在底部的问题
要让小计、税费、总计这类汇总行不受排序影响始终固定在表格底部,有两种实用的实现方式,可根据需求选择:
方法1:使用DataGrid自定义Footer组件(推荐)
把业务数据行和汇总行拆分,汇总行单独放在表格的Footer区域,彻底隔离排序逻辑,不管怎么排序,Footer内容都不会变动。
实现步骤:
- 拆分数据源,将业务数据与汇总数据分为两个独立数组
- 自定义Footer组件,匹配DataGrid样式渲染汇总行
- 在DataGrid中配置
components.Footer使用自定义组件
import { DataGrid } from '@mui/x-data-grid'; // 业务数据行 const dataRows = [ { id: 1, item: "商品A", amount: 150 }, { id: 2, item: "商品B", amount: 280 }, { id: 3, item: "商品C", amount: 90 }, ]; // 汇总数据行 const summaryData = [ { id: 'subtotal', label: '小计', value: 520 }, { id: 'tax', label: '税费', value: 52 }, { id: 'total', label: '总计', value: 572 }, ]; // 自定义Footer组件,对齐表格样式 const SummaryFooter = () => ( <div style={{ borderTop: '2px solid #e0e0e0', padding: '12px 16px', backgroundColor: '#fafafa' }}> {summaryData.map(row => ( <div key={row.id} style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontWeight: row.id === 'total' ? 'bold' : 'normal' }} > <span>{row.label}</span> <span>${row.value.toFixed(2)}</span> </div> ))} </div> ); // 表格列配置 const columns = [ { field: 'item', headerName: '商品', width: 150 }, { field: 'amount', headerName: '金额', width: 150 }, ]; export default function MyDataGrid() { return ( <div style={{ height: 400, width: '100%' }}> <DataGrid rows={dataRows} columns={columns} components={{ Footer: SummaryFooter }} /> </div> ); }
这种方式代码简洁,利用DataGrid内置组件能力,无需手动处理排序逻辑,汇总行与业务行的视觉区分也更清晰。
方法2:手动处理排序逻辑,追加汇总行到结果末尾
如果需要汇总行与业务数据行处于同一表格区域(比如保持统一单元格样式),可以在排序完成后手动将汇总行追加到最后。
实现步骤:
- 给汇总行添加标识(如
isSummary: true),方便区分 - 监听排序模型变化,分离业务行与汇总行,单独排序业务行后再合并
import { DataGrid } from '@mui/x-data-grid'; import { useState, useEffect } from 'react'; // 包含业务行和汇总行的数据源,汇总行添加isSummary标识 const allRows = [ { id: 1, item: "商品A", amount: 150, isSummary: false }, { id: 2, item: "商品B", amount: 280, isSummary: false }, { id: 3, item: "商品C", amount: 90, isSummary: false }, { id: 'subtotal', item: '小计', amount: 520, isSummary: true }, { id: 'tax', item: '税费', amount: 52, isSummary: true }, { id: 'total', item: '总计', amount: 572, isSummary: true }, ]; const columns = [ { field: 'item', headerName: '商品/汇总项', width: 150 }, { field: 'amount', headerName: '金额', width: 150 }, ]; export default function MyDataGrid() { const [sortModel, setSortModel] = useState([]); const [sortedRows, setSortedRows] = useState(allRows); useEffect(() => { if (!sortModel.length) { setSortedRows(allRows); return; } // 分离业务行和汇总行 const dataRows = allRows.filter(row => !row.isSummary); const summaryRows = allRows.filter(row => row.isSummary); // 按当前排序规则对业务行排序 const { field, sort } = sortModel[0]; const sortedData = [...dataRows].sort((a, b) => { if (a[field] < b[field]) { return sort === 'asc' ? -1 : 1; } if (a[field] > b[field]) { return sort === 'asc' ? 1 : -1; } return 0; }); // 合并排序后的业务行与汇总行(汇总行始终在最后) setSortedRows([...sortedData, ...summaryRows]); }, [sortModel]); return ( <div style={{ height: 400, width: '100%' }}> <DataGrid rows={sortedRows} columns={columns} sortModel={sortModel} onSortModelChange={setSortModel} // 可选:给汇总行添加特殊样式区分 getRowClassName={(params) => params.row.isSummary ? 'summary-row' : ''} /> </div> ); }
可配合CSS给汇总行添加样式:
.summary-row { background-color: #fafafa; font-weight: 500; }
这种方式适合需要汇总行与业务行视觉统一的场景,但需要自行维护排序逻辑,相对繁琐一些。
内容的提问来源于stack exchange,提问作者Rajat
相关产品推荐
相关产品推荐

