如何为Material UI Table设置默认按Protein排序(非DataGrid)
为Material UI Table设置默认按Protein字段排序
要实现表格加载时默认按Protein字段排序且不需要表头排序按钮,最简单的方案就是在渲染表格前对数据进行排序——因为Material UI的基础Table组件本身没有内置排序功能,直接处理数据源即可满足需求。
具体实现步骤
- 创建排序后的数据源:对原
rows数组做浅拷贝(避免修改原始数据),再用sort()方法按protein字段排序。 - 渲染表格时使用排序后的数组替代原数组。
修改后的完整代码
import * as React from 'react'; import PropTypes from 'prop-types'; import Box from '@mui/material/Box'; import Collapse from '@mui/material/Collapse'; import IconButton from '@mui/material/IconButton'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; function createData(name, calories, fat, carbs, protein, price) { return { name, calories, fat, carbs, protein, price, history: [ { date: '2020-01-05', customerId: '11091700', amount: 3, }, { date: '2020-01-02', customerId: 'Anonymous', amount: 1, }, ], }; } function Row(props) { const { row } = props; const [open, setOpen] = React.useState(false); return ( <React.Fragment> <TableRow sx={{ '& > *': { borderBottom: 'unset' } }}> <TableCell> <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)} > {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} </IconButton> </TableCell> <TableCell component="th" scope="row"> {row.name} </TableCell> <TableCell align="right">{row.calories}</TableCell> <TableCell align="right">{row.fat}</TableCell> <TableCell align="right">{row.carbs}</TableCell> <TableCell align="right">{row.protein}</TableCell> </TableRow> <TableRow> <TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}> <Collapse in={open} timeout="auto" unmountOnExit> <Box sx={{ margin: 1 }}> <Typography variant="h6" gutterBottom component="div"> History </Typography> <Table size="small" aria-label="purchases"> <TableHead> <TableRow> <TableCell>Date</TableCell> <TableCell>Customer</TableCell> <TableCell align="right">Amount</TableCell> <TableCell align="right">Total price ($)</TableCell> </TableRow> </TableHead> <TableBody> {row.history.map((historyRow) => ( <TableRow key={historyRow.date}> <TableCell component="th" scope="row"> {historyRow.date} </TableCell> <TableCell>{historyRow.customerId}</TableCell> <TableCell align="right">{historyRow.amount}</TableCell> <TableCell align="right"> {Math.round(historyRow.amount * row.price * 100) / 100} </TableCell> </TableRow> ))} </TableBody> </Table> </Box> </Collapse> </TableCell> </TableRow> </React.Fragment> ); } Row.propTypes = { row: PropTypes.shape({ calories: PropTypes.number.isRequired, carbs: PropTypes.number.isRequired, fat: PropTypes.number.isRequired, history: PropTypes.arrayOf( PropTypes.shape({ amount: PropTypes.number.isRequired, customerId: PropTypes.string.isRequired, date: PropTypes.string.isRequired, }), ).isRequired, name: PropTypes.string.isRequired, price: PropTypes.number.isRequired, protein: PropTypes.number.isRequired, }).isRequired, }; const rows = [ createData('Frozen yoghurt', 159, 6.0, 24, 4.0, 3.99), createData('Ice cream sandwich', 237, 9.0, 37, 4.3, 4.99), createData('Eclair', 262, 16.0, 24, 6.0, 3.79), createData('Cupcake', 305, 3.7, 67, 4.3, 2.5), createData('Gingerbread', 356, 16.0, 49, 3.9, 1.5), ]; export default function CollapsibleTable() { // 按Protein字段升序排序,需降序则改为 b.protein - a.protein const sortedRows = [...rows].sort((a, b) => a.protein - b.protein); return ( <TableContainer component={Paper}> <Table aria-label="collapsible table"> <TableHead> <TableRow> <TableCell /> <TableCell>Dessert (100g serving)</TableCell> <TableCell align="right">Calories</TableCell> <TableCell align="right">Fat (g)</TableCell> <TableCell align="right">Carbs (g)</TableCell> <TableCell align="right">Protein (g)</TableCell> </TableRow> </TableHead> <TableBody> {sortedRows.map((row) => ( <Row key={row.name} row={row} /> ))} </TableBody> </Table> </TableContainer> ); }
关键细节说明
- 使用
[...rows]创建原数组的浅拷贝,防止直接修改原始数据引发不必要的副作用。 - 排序逻辑可灵活调整:
a.protein - b.protein实现升序,b.protein - a.protein实现降序。 - 若数据来自API动态获取,可将排序逻辑放在
useEffect钩子中,确保数据加载完成后再执行排序。
内容的提问来源于stack exchange,提问作者Colin S
相关产品推荐
相关产品推荐

