Material-UI 数据展示组件 #
概述 #
MUI 提供了丰富的数据展示组件,用于呈现各种类型的数据。
text
数据展示组件体系
│
├── Typography 文字排版
├── Table 表格
├── Card 卡片
├── List 列表
├── Avatar 头像
├── Chip 标签
├── Badge 徽章
├── Divider 分隔线
├── Tooltip 提示
└── Collapse 折叠面板
Typography 文字排版 #
变体 #
jsx
import { Typography, Stack } from '@mui/material';
<Stack spacing={1}>
<Typography variant="h1">H1 标题</Typography>
<Typography variant="h2">H2 标题</Typography>
<Typography variant="h3">H3 标题</Typography>
<Typography variant="h4">H4 标题</Typography>
<Typography variant="h5">H5 标题</Typography>
<Typography variant="h6">H6 标题</Typography>
<Typography variant="subtitle1">Subtitle 1</Typography>
<Typography variant="subtitle2">Subtitle 2</Typography>
<Typography variant="body1">Body 1 正文内容</Typography>
<Typography variant="body2">Body 2 正文内容</Typography>
<Typography variant="button">Button 文字</Typography>
<Typography variant="caption">Caption 说明文字</Typography>
<Typography variant="overline">Overline 标题线</Typography>
</Stack>
颜色 #
jsx
<Stack spacing={1}>
<Typography color="primary">Primary 主色</Typography>
<Typography color="secondary">Secondary 次色</Typography>
<Typography color="error">Error 错误</Typography>
<Typography color="text.primary">Text Primary</Typography>
<Typography color="text.secondary">Text Secondary</Typography>
<Typography color="text.disabled">Text Disabled</Typography>
</Stack>
对齐 #
jsx
<Box sx={{ width: '100%' }}>
<Typography align="left">左对齐</Typography>
<Typography align="center">居中</Typography>
<Typography align="right">右对齐</Typography>
<Typography align="justify">
两端对齐:这是一段较长的文字内容,用于演示两端对齐的效果。
</Typography>
</Box>
其他属性 #
jsx
<Stack spacing={1}>
<Typography noWrap sx={{ width: 100 }}>
这是一段超长的文字内容,会被截断并显示省略号
</Typography>
<Typography gutterBottom>带底部间距</Typography>
<Typography paragraph>段落文字(带底部间距)</Typography>
<Typography fontWeight="bold">粗体文字</Typography>
<Typography fontStyle="italic">斜体文字</Typography>
</Stack>
Table 表格 #
基础表格 #
jsx
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper } from '@mui/material';
function BasicTable() {
const rows = [
{ name: 'Frozen yoghurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0 },
{ name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3 },
{ name: 'Eclair', calories: 262, fat: 16.0, carbs: 24, protein: 6.0 },
];
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<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>
{rows.map((row) => (
<TableRow
key={row.name}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<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>
))}
</TableBody>
</Table>
</TableContainer>
);
}
密度表格 #
jsx
<TableContainer component={Paper}>
<Table size="small" aria-label="a dense table">
{/* ... */}
</Table>
</TableContainer>
条纹表格 #
jsx
<TableContainer component={Paper}>
<Table sx={{ '& .MuiTableRow-root:hover': { backgroundColor: 'action.hover' } }}>
{/* ... */}
</Table>
</TableContainer>
固定表头 #
jsx
<TableContainer sx={{ maxHeight: 440 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>Column 1</TableCell>
<TableCell>Column 2</TableCell>
</TableRow>
</TableHead>
<TableBody>
{/* ... */}
</TableBody>
</Table>
</TableContainer>
分页表格 #
jsx
import { TablePagination } from '@mui/material';
function PaginatedTable() {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
return (
<Paper>
<TableContainer>
<Table>{/* ... */}</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={rows.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
labelRowsPerPage="每页行数:"
labelDisplayedRows={({ from, to, count }) => `${from}-${to} 共 ${count} 条`}
/>
</Paper>
);
}
Card 卡片 #
基础卡片 #
jsx
import { Card, CardContent, CardMedia, CardActions, Typography, Button } from '@mui/material';
<Card sx={{ maxWidth: 345 }}>
<CardMedia
component="img"
height="140"
image="/static/images/cards/contemplative-reptile.jpg"
alt="green iguana"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
蜥蜴
</Typography>
<Typography variant="body2" color="text.secondary">
蜥蜴是一类广泛分布的爬行动物,全球有超过6000种。
</Typography>
</CardContent>
<CardActions>
<Button size="small">分享</Button>
<Button size="small">了解更多</Button>
</CardActions>
</Card>
简单卡片 #
jsx
<Card sx={{ minWidth: 275 }}>
<CardContent>
<Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
单词卡片
</Typography>
<Typography variant="h5" component="div">
be•nev•o•lent
</Typography>
<Typography sx={{ mb: 1.5 }} color="text.secondary">
形容词
</Typography>
<Typography variant="body2">
善良的,仁慈的
<br />
{'"她是一个善良的人"'}
</Typography>
</CardContent>
<CardActions>
<Button size="small">了解更多</Button>
</CardActions>
</Card>
媒体卡片 #
jsx
<Card>
<CardHeader
avatar={<Avatar aria-label="recipe">R</Avatar>}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title="Shrimp and Chorizo Paella"
subheader="September 14, 2016"
/>
<CardMedia
component="img"
height="194"
image="/static/images/cards/paella.jpg"
alt="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
这是一道令人印象深刻的派对菜肴。
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
</CardActions>
</Card>
卡片组 #
jsx
<Grid container spacing={3}>
{cards.map((card) => (
<Grid item key={card.id} xs={12} sm={6} md={4}>
<Card sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
<CardMedia
component="img"
height="140"
image={card.image}
alt={card.title}
/>
<CardContent sx={{ flexGrow: 1 }}>
<Typography gutterBottom variant="h5">
{card.title}
</Typography>
<Typography>{card.description}</Typography>
</CardContent>
<CardActions>
<Button size="small">查看</Button>
<Button size="small">编辑</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
List 列表 #
基础列表 #
jsx
import { List, ListItem, ListItemButton, ListItemIcon, ListItemText, Divider } from '@mui/material';
import { Inbox as InboxIcon, Drafts as DraftsIcon } from '@mui/icons-material';
<List>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="收件箱" />
</ListItemButton>
</ListItem>
<ListItem disablePadding>
<ListItemButton>
<ListItemIcon>
<DraftsIcon />
</ListItemIcon>
<ListItemText primary="草稿" />
</ListItemButton>
</ListItem>
</List>
嵌套列表 #
jsx
import { ListSubheader, Collapse } from '@mui/material';
import { ExpandLess, ExpandMore, StarBorder } from '@mui/icons-material';
function NestedList() {
const [open, setOpen] = useState(true);
return (
<List
component="nav"
subheader={<ListSubheader>嵌套列表</ListSubheader>}
>
<ListItemButton onClick={() => setOpen(!open)}>
<ListItemIcon><InboxIcon /></ListItemIcon>
<ListItemText primary="收件箱" />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItemButton sx={{ pl: 4 }}>
<ListItemIcon><StarBorder /></ListItemIcon>
<ListItemText primary="星标邮件" />
</ListItemButton>
</List>
</Collapse>
</List>
);
}
带头像的列表 #
jsx
<List>
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
</ListItemAvatar>
<ListItemText
primary="Brunch this weekend?"
secondary={
<React.Fragment>
<Typography sx={{ display: 'inline' }} component="span" variant="body2" color="text.primary">
Ali Connors
</Typography>
{" — I'll be in your neighborhood doing errands this…"}
</React.Fragment>
}
/>
</ListItem>
<Divider variant="inset" component="li" />
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
</ListItemAvatar>
<ListItemText primary="Summer BBQ" secondary="4:00 PM" />
</ListItem>
</List>
可选列表 #
jsx
function SelectedListItem() {
const [selectedIndex, setSelectedIndex] = useState(1);
return (
<List component="nav">
<ListItemButton
selected={selectedIndex === 0}
onClick={() => setSelectedIndex(0)}
>
<ListItemIcon><InboxIcon /></ListItemIcon>
<ListItemText primary="收件箱" />
</ListItemButton>
<ListItemButton
selected={selectedIndex === 1}
onClick={() => setSelectedIndex(1)}
>
<ListItemIcon><DraftsIcon /></ListItemIcon>
<ListItemText primary="草稿" />
</ListItemButton>
</List>
);
}
Avatar 头像 #
基础用法 #
jsx
import { Avatar, Stack } from '@mui/material';
<Stack direction="row" spacing={2}>
<Avatar>H</Avatar>
<Avatar sx={{ bgcolor: 'primary.main' }}>N</Avatar>
<Avatar sx={{ bgcolor: 'secondary.main' }}>OP</Avatar>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
</Stack>
尺寸 #
jsx
<Stack direction="row" spacing={2}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" sx={{ width: 24, height: 24 }} />
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" sx={{ width: 56, height: 56 }} />
</Stack>
图标头像 #
jsx
import { Folder as FolderIcon, Pageview as PageviewIcon, Assignment as AssignmentIcon } from '@mui/icons-material';
<Stack direction="row" spacing={2}>
<Avatar>
<FolderIcon />
</Avatar>
<Avatar sx={{ bgcolor: 'primary.main' }}>
<PageviewIcon />
</Avatar>
<Avatar sx={{ bgcolor: 'secondary.main' }}>
<AssignmentIcon />
</Avatar>
</Stack>
变体 #
jsx
<Stack direction="row" spacing={2}>
<Avatar variant="square">S</Avatar>
<Avatar variant="rounded">R</Avatar>
<Avatar variant="circular">C</Avatar>
</Stack>
头像组 #
jsx
import { AvatarGroup } from '@mui/material';
<AvatarGroup max={4}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
<Avatar alt="Travis Howard" src="/static/images/avatar/2.jpg" />
<Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" />
<Avatar alt="Agnes Walker" src="/static/images/avatar/4.jpg" />
<Avatar alt="Trevor Henderson" src="/static/images/avatar/5.jpg" />
</AvatarGroup>
Chip 标签 #
基础用法 #
jsx
import { Chip, Stack } from '@mui/material';
<Stack direction="row" spacing={1}>
<Chip label="Chip Filled" />
<Chip label="Chip Outlined" variant="outlined" />
</Stack>
可点击 #
jsx
<Stack direction="row" spacing={1}>
<Chip label="Clickable" onClick={() => console.log('clicked')} />
<Chip label="Clickable Link" component="a" href="#basic-chip" clickable />
</Stack>
可删除 #
jsx
<Stack direction="row" spacing={1}>
<Chip label="Deletable" onDelete={() => console.log('delete')} />
<Chip label="Deletable Link" component="a" href="#chip-deletable" onDelete={() => {}} />
</Stack>
带头像 #
jsx
<Stack direction="row" spacing={1}>
<Chip avatar={<Avatar>M</Avatar>} label="Avatar" />
<Chip avatar={<Avatar alt="Natacha" src="/static/images/avatar/1.jpg" />} label="Avatar" variant="outlined" />
</Stack>
带图标 #
jsx
import { Face as FaceIcon, Tag as TagIcon } from '@mui/icons-material';
<Stack direction="row" spacing={1}>
<Chip icon={<FaceIcon />} label="With Icon" />
<Chip icon={<TagIcon />} label="With Icon" variant="outlined" />
</Stack>
颜色 #
jsx
<Stack direction="row" spacing={1}>
<Chip label="Primary" color="primary" />
<Chip label="Success" color="success" />
<Chip label="Error" color="error" />
<Chip label="Warning" color="warning" />
<Chip label="Info" color="info" />
</Stack>
尺寸 #
jsx
<Stack direction="row" spacing={1}>
<Chip label="Small" size="small" />
<Chip label="Medium" size="medium" />
</Stack>
Badge 徽章 #
基础用法 #
jsx
import { Badge, IconButton, MailIcon } from '@mui/material';
<Badge badgeContent={4} color="primary">
<MailIcon />
</Badge>
颜色 #
jsx
<Stack direction="row" spacing={2}>
<Badge badgeContent={4} color="secondary">
<MailIcon color="action" />
</Badge>
<Badge badgeContent={4} color="success">
<MailIcon color="action" />
</Badge>
<Badge badgeContent={4} color="error">
<MailIcon color="action" />
</Badge>
</Stack>
最大值 #
jsx
<Badge badgeContent={100} color="primary">
<MailIcon />
</Badge>
点徽章 #
jsx
<Badge color="secondary" variant="dot">
<MailIcon />
</Badge>
对齐 #
jsx
<Stack direction="row" spacing={2}>
<Badge badgeContent={4} color="primary" anchorOrigin={{ vertical: 'top', horizontal: 'right' }}>
<MailIcon />
</Badge>
<Badge badgeContent={4} color="primary" anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}>
<MailIcon />
</Badge>
</Stack>
Tooltip 提示 #
基础用法 #
jsx
import { Tooltip, Button } from '@mui/material';
<Tooltip title="删除">
<IconButton>
<DeleteIcon />
</IconButton>
</Tooltip>
位置 #
jsx
<Stack direction="row" spacing={2}>
<Tooltip title="上" placement="top"><Button>Top</Button></Tooltip>
<Tooltip title="下" placement="bottom"><Button>Bottom</Button></Tooltip>
<Tooltip title="左" placement="left"><Button>Left</Button></Tooltip>
<Tooltip title="右" placement="right"><Button>Right</Button></Tooltip>
</Stack>
箭头 #
jsx
<Tooltip title="带箭头" arrow>
<Button>Arrow</Button>
</Tooltip>
延迟 #
jsx
<Tooltip title="延迟显示" enterDelay={500} leaveDelay={200}>
<Button>Delayed</Button>
</Tooltip>
禁用 #
jsx
<Tooltip title="禁用时不显示">
<span>
<Button disabled>Disabled Button</Button>
</span>
</Tooltip>
下一步 #
继续学习 反馈组件,了解对话框、消息提示等交互组件!
最后更新:2026-03-28