You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Material UI DataGrid排序时固定汇总行至底部

解决Material UI DataGrid汇总行固定在底部的问题

要让小计、税费、总计这类汇总行不受排序影响始终固定在表格底部,有两种实用的实现方式,可根据需求选择:

方法1:使用DataGrid自定义Footer组件(推荐)

把业务数据行和汇总行拆分,汇总行单独放在表格的Footer区域,彻底隔离排序逻辑,不管怎么排序,Footer内容都不会变动。

实现步骤:

  1. 拆分数据源,将业务数据与汇总数据分为两个独立数组
  2. 自定义Footer组件,匹配DataGrid样式渲染汇总行
  3. 在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:手动处理排序逻辑,追加汇总行到结果末尾

如果需要汇总行与业务数据行处于同一表格区域(比如保持统一单元格样式),可以在排序完成后手动将汇总行追加到最后。

实现步骤:

  1. 给汇总行添加标识(如isSummary: true),方便区分
  2. 监听排序模型变化,分离业务行与汇总行,单独排序业务行后再合并
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:01:19