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&nbsp;(g)</TableCell>
            <TableCell align="right">Carbs&nbsp;(g)</TableCell>
            <TableCell align="right">Protein&nbsp;(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