MUI X Data Grid:实现树形数据网格的全量展开与收起控制

1次阅读

MUI X Data Grid:实现树形数据网格的全量展开与收起控制

本文详解如何在 Mui X Data Grid 中通过受控模式(controlled state)实现「展开全部」和「收起全部」按钮的稳定响应,彻底解决 defaultGroupingExpansionDepth 在动态交互后失效的问题。

本文详解如何在 mui x data grid 中通过受控模式(controlled state)实现「展开全部」和「收起全部」按钮的稳定响应,彻底解决 `defaultgroupingexpansiondepth` 在动态交互后失效的问题。

在使用 MUI X Data Grid 构建树形结构(treeData={true})时,开发者常希望通过按钮一键控制所有分组节点的展开/收起状态。虽然官方文档推荐使用 defaultGroupingExpansionDepth(如设为 -1 展开全部、0 收起全部),但该属性仅在组件初始化或重渲染时生效,无法响应运行时的交互变更——一旦用户手动点击某一行展开/收起,后续再点击“展开全部”按钮便不再触发更新,导致 UI 状态与预期脱节。

根本原因在于:defaultGroupingExpansionDepth 是非受控属性(uncontrolled),而树形网格的展开状态实际由内部状态管理。要实现可靠的全量控制,必须采用完全受控模式(controlled mode),即显式接管并同步 groupingExpansionState,并通过 onGroupingExpandedChange 响应用户操作。

✅ 正确实现方式:受控展开状态

以下是一个完整、可复用的解决方案:

import * as React from 'react'; import { DataGridPro, GridGroupingExpansionState } from '@mui/x-data-grid-pro'; import { Stack, Button } from '@mui/material';  // 定义状态常量(语义化提升可读性) const EXPAND_ALL = true; const COLLAPSE_ALL = false;  export default function ExpandCollapseAllGrid() {   const [expandedState, setExpandedState] = React.useState<GridGroupingExpansionState>(COLLAPSE_ALL);   const dataGridApi = React.useRef(null);    return (     <Stack spacing={2}>       {/* 控制按钮 */}       <Stack direction="row" spacing={1} p={1}>         <Button           variant="contained"           size="small"           onClick={() => setExpandedState(EXPAND_ALL)}         >           展开全部         </Button>         <Button           variant="outlined"           size="small"           onClick={() => setExpandedState(COLLAPSE_ALL)}         >           收起全部         </Button>       </Stack>        {/* 受控 DataGridPro */}       <DataGridPro         treeData         rows={rows} // 替换为你的树形数据(需含 `parentId` 字段)         columns={columns}         apiRef={dataGridApi}          // ? 关键:使用 groupingExpansionState 替代 defaultGroupingExpansionDepth         groupingExpansionState={expandedState}          // ? 关键:监听用户手动展开/收起行为,保持状态同步         onGroupingExpandedChange={(params) => {           // 注意:此处不直接设为 params.expanded,           // 因为用户单击某节点时,params.expanded 表示该节点新状态,           // 而我们维护的是全局统一状态(全展开 / 全收起)           // 所以建议:若需支持混合状态(部分展开),应改用 Map 管理各 groupId;           // 但本例聚焦「全量控制」,故保持布尔值语义           setExpandedState(params.expanded ? EXPAND_ALL : COLLAPSE_ALL);         }}          // 其他必要配置         getRowId={(row) => row.id}         getTreeDataPath={(row) => row.hierarchy || [row.id]} // 根据数据结构调整         disableSelectionOnClick       />     </Stack>   ); }

⚠️ 注意事项与最佳实践

  • groupingExpansionState 类型:其类型为 GridGroupingExpansionState(即 Boolean | Record)。上例中使用 boolean 是最简场景;若需更精细控制(例如仅展开某一层级或特定分组),应切换为 Record 并配合 groupId 管理。
  • 避免与 defaultGroupingExpansionDepth 混用:二者互斥。启用 groupingExpansionState 后,请务必移除 defaultGroupingExpansionDepth,否则可能引发状态冲突或警告。
  • 性能考量:对超大数据集(>5000 行),全量展开可能造成渲染卡顿。建议结合 pagination 或 virtualization(默认启用)确保流畅体验。
  • 无障碍支持:MUI X 自动为展开/收起按钮添加 aria-expanded 和键盘导航(Enter/Space 触发),无需额外处理。

✅ 总结

defaultGroupingExpansionDepth 适用于静态初始态,而真正的交互式全量控制必须依赖受控属性 groupingExpansionState + onGroupingExpandedChange。该方案解耦了 UI 操作与内部状态,确保按钮无论在任何当前状态(全收起、部分展开、全展开)下均能可靠生效,是构建专业级树形数据网格的推荐实践。

text=ZqhQzanResources