如何让可折叠表格中折叠行的单元格与展开行单元格对齐
问题原因
你的代码中折叠行的结构不符合HTML表格规范:非首条taskAction对应的行里,你用一个设置了colSpan={9}的TableCell占满整行后,直接把9个TableCell放在Collapse组件内,这些单元格没有父级TableRow,也不属于外层表格的行结构,浏览器不会按外层表头的列宽进行排版,因此出现对齐错乱。
修复方案
这里提供两种常用实现方式,按需选择即可:
方案1:保留展开/收起动画(推荐)
参考MUI官方可折叠表格的实现逻辑,在Collapse内部嵌套一个和外层表头结构完全一致的内部表格,自动继承外层列宽实现对齐,修改后的代码如下:
function Task(props: { task: taskProps }) { const { task } = props; const [open, setOpen] = React.useState(false); // 拆分首条展示action和剩余折叠action,避免map中判断索引 const [firstAction, ...restActions] = task.tasksActions; return ( <> {/* 首行可展开头部,逻辑保持不变 */} <TableRow> <TableCell> <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)} > {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} </IconButton> </TableCell> <TableCell>{task.taskId}</TableCell> <TableCell>{firstAction.actionId}</TableCell> <TableCell>{firstAction.templateStepId}</TableCell> <TableCell>{firstAction.templateStepName}</TableCell> <TableCell>100</TableCell> <TableCell>{firstAction.startedAt}</TableCell> <TableCell>{firstAction.endedAt}</TableCell> <TableCell>{firstAction.status}</TableCell> </TableRow> {/* 折叠内容容器行 */} <TableRow> <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={9}> <Collapse in={open} timeout="auto" unmountOnExit> {/* 内部表格结构和外层表头完全对应,保证对齐 */} <Table size="small" sx={{ border: 0 }}> <TableBody> {restActions.map((taskAction, index) => ( <TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}> <TableCell padding="none">{/* 对应外层展开按钮列,留空对齐 */}</TableCell> <TableCell>{task.taskId}</TableCell> <TableCell>{taskAction.actionId}</TableCell> <TableCell>{taskAction.templateStepId}</TableCell> <TableCell>{taskAction.templateStepName}</TableCell> <TableCell>100</TableCell> <TableCell>{taskAction.startedAt}</TableCell> <TableCell>{taskAction.endedAt}</TableCell> <TableCell>{taskAction.status}</TableCell> </TableRow> ))} </TableBody> </Table> </Collapse> </TableCell> </TableRow> </> ); } // 外层MetricsTable组件无需修改
代码中新增的sx样式用于移除内部表格的多余边框,保证和外层表格视觉统一。
方案2:无动画,对齐最精准
如果不需要展开收起的过渡动画,可以直接把剩余的action渲染为外层表格的直接子行,通过display属性控制显示隐藏,天然继承外层表格的列宽,对齐效果最完美:
function Task(props: { task: taskProps }) { const { task } = props; const [open, setOpen] = React.useState(false); const [firstAction, ...restActions] = task.tasksActions; return ( <> {/* 首行可展开头部 */} <TableRow> <TableCell> <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)} > {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} </IconButton> </TableCell> <TableCell>{task.taskId}</TableCell> <TableCell>{firstAction.actionId}</TableCell> <TableCell>{firstAction.templateStepId}</TableCell> <TableCell>{firstAction.templateStepName}</TableCell> <TableCell>100</TableCell> <TableCell>{firstAction.startedAt}</TableCell> <TableCell>{firstAction.endedAt}</TableCell> <TableCell>{firstAction.status}</TableCell> </TableRow> {/* 剩余action直接渲染为普通行,控制显示隐藏 */} {restActions.map((taskAction, index) => ( <TableRow key={index} style={{ display: open ? 'table-row' : 'none' }}> <TableCell>{/* 对应外层展开按钮列,留空对齐 */}</TableCell> <TableCell>{task.taskId}</TableCell> <TableCell>{taskAction.actionId}</TableCell> <TableCell>{taskAction.templateStepId}</TableCell> <TableCell>{taskAction.templateStepName}</TableCell> <TableCell>100</TableCell> <TableCell>{taskAction.startedAt}</TableCell> <TableCell>{taskAction.endedAt}</TableCell> <TableCell>{taskAction.status}</TableCell> </TableRow> ))} </> ); }
内容的提问来源于stack exchange,提问作者Amravi
相关产品推荐
相关产品推荐

