Material-UI 快速开始 #

创建第一个 MUI 应用 #

让我们从创建一个简单的登录页面开始,逐步了解 MUI 的核心概念。

完整示例 #

jsx
import {
  Container,
  Box,
  TextField,
  Button,
  Typography,
  Link,
  Card,
  CardContent,
} from '@mui/material';

function LoginPage() {
  return (
    <Container maxWidth="sm">
      <Box sx={{ mt: 8 }}>
        <Card>
          <CardContent sx={{ p: 4 }}>
            <Typography variant="h4" align="center" gutterBottom>
              登录
            </Typography>
            <Box component="form" sx={{ mt: 2 }}>
              <TextField
                fullWidth
                label="邮箱地址"
                type="email"
                margin="normal"
              />
              <TextField
                fullWidth
                label="密码"
                type="password"
                margin="normal"
              />
              <Button
                type="submit"
                fullWidth
                variant="contained"
                sx={{ mt: 3, mb: 2 }}
              >
                登录
              </Button>
              <Typography align="center">
                <Link href="#">忘记密码?</Link>
              </Typography>
            </Box>
          </CardContent>
        </Card>
      </Box>
    </Container>
  );
}

export default LoginPage;

核心概念 #

1. 组件导入 #

MUI 组件从 @mui/material 导入:

jsx
import {
  Button,
  TextField,
  Container,
  Box,
  Typography,
} from '@mui/material';

2. ThemeProvider 和 CssBaseline #

ThemeProvider 提供主题上下文,CssBaseline 提供全局样式重置:

jsx
import { ThemeProvider, CssBaseline, createTheme } from '@mui/material';

const theme = createTheme();

function App() {
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <LoginPage />
    </ThemeProvider>
  );
}

3. sx Prop #

sx prop 是 MUI 最强大的样式工具:

jsx
<Box
  sx={{
    p: 2,
    m: 1,
    bgcolor: 'primary.main',
    color: 'white',
    borderRadius: 1,
  }}
>
  sx prop 示例
</Box>

常用组件速览 #

布局组件 #

Container #

容器组件,用于限制内容宽度:

jsx
<Container maxWidth="sm">
  小容器 (600px)
</Container>

<Container maxWidth="md">
  中等容器 (900px)
</Container>

<Container maxWidth="lg">
  大容器 (1200px)
</Container>

Box #

通用容器,类似 <div>

jsx
<Box sx={{ p: 2, bgcolor: 'grey.100' }}>
  这是一个 Box
</Box>

Stack #

堆叠布局,用于垂直或水平排列:

jsx
<Stack spacing={2} direction="column">
  <Box>项目 1</Box>
  <Box>项目 2</Box>
  <Box>项目 3</Box>
</Stack>

<Stack spacing={2} direction="row">
  <Box>项目 1</Box>
  <Box>项目 2</Box>
  <Box>项目 3</Box>
</Stack>

Grid #

网格布局系统:

jsx
<Grid container spacing={2}>
  <Grid item xs={12} md={6}>
    <Box sx={{ bgcolor: 'primary.light', p: 2 }}>左侧</Box>
  </Grid>
  <Grid item xs={12} md={6}>
    <Box sx={{ bgcolor: 'secondary.light', p: 2 }}>右侧</Box>
  </Grid>
</Grid>

输入组件 #

Button #

按钮组件:

jsx
<Stack spacing={2} direction="row">
  <Button variant="text">Text</Button>
  <Button variant="contained">Contained</Button>
  <Button variant="outlined">Outlined</Button>
</Stack>

<Stack spacing={2} direction="row" sx={{ mt: 2 }}>
  <Button color="primary">Primary</Button>
  <Button color="secondary">Secondary</Button>
  <Button color="error">Error</Button>
  <Button color="success">Success</Button>
</Stack>

TextField #

文本输入框:

jsx
<Stack spacing={2}>
  <TextField label="标准输入" variant="standard" />
  <TextField label="填充输入" variant="filled" />
  <TextField label="轮廓输入" variant="outlined" />
  
  <TextField
    label="带错误提示"
    error
    helperText="请输入有效内容"
  />
  
  <TextField
    label="禁用状态"
    disabled
  />
</Stack>

Select #

选择器:

jsx
import { FormControl, InputLabel, Select, MenuItem } from '@mui/material';

function BasicSelect() {
  const [age, setAge] = useState('');

  return (
    <FormControl fullWidth>
      <InputLabel>年龄</InputLabel>
      <Select
        value={age}
        label="年龄"
        onChange={(e) => setAge(e.target.value)}
      >
        <MenuItem value={10}>10岁</MenuItem>
        <MenuItem value={20}>20岁</MenuItem>
        <MenuItem value={30}>30岁</MenuItem>
      </Select>
    </FormControl>
  );
}

Checkbox 和 Radio #

jsx
import { FormControlLabel, Checkbox, Radio, RadioGroup } from '@mui/material';

<Stack spacing={2}>
  <FormControlLabel control={<Checkbox />} label="同意条款" />
  
  <RadioGroup defaultValue="male">
    <FormControlLabel value="male" control={<Radio />} label="男" />
    <FormControlLabel value="female" control={<Radio />} label="女" />
  </RadioGroup>
</Stack>

数据展示组件 #

Typography #

文字排版:

jsx
<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">副标题 1</Typography>
  <Typography variant="subtitle2">副标题 2</Typography>
  <Typography variant="body1">正文 1</Typography>
  <Typography variant="body2">正文 2</Typography>
  <Typography variant="caption">说明文字</Typography>
</Stack>

Card #

卡片组件:

jsx
<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>

Avatar #

头像组件:

jsx
<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" />
</Stack>

反馈组件 #

Dialog #

对话框:

jsx
import { Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';

function AlertDialog() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button variant="outlined" onClick={() => setOpen(true)}>
        打开对话框
      </Button>
      <Dialog open={open} onClose={() => setOpen(false)}>
        <DialogTitle>确认操作</DialogTitle>
        <DialogContent>
          <Typography>你确定要执行此操作吗?</Typography>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setOpen(false)}>取消</Button>
          <Button onClick={() => setOpen(false)} autoFocus>
            确认
          </Button>
        </DialogActions>
      </Dialog>
    </>
  );
}

Snackbar #

消息提示:

jsx
import { Snackbar, Alert } from '@mui/material';

function SimpleSnackbar() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setOpen(true)}>显示消息</Button>
      <Snackbar
        open={open}
        autoHideDuration={3000}
        onClose={() => setOpen(false)}
      >
        <Alert severity="success">操作成功!</Alert>
      </Snackbar>
    </>
  );
}

Progress #

进度指示器:

jsx
<Stack spacing={2} direction="row">
  <CircularProgress />
  <CircularProgress color="secondary" />
  <CircularProgress variant="determinate" value={75} />
</Stack>

<Stack spacing={2} sx={{ mt: 2 }}>
  <LinearProgress />
  <LinearProgress color="secondary" />
  <LinearProgress variant="determinate" value={50} />
</Stack>

实战示例:简单仪表板 #

jsx
import {
  AppBar,
  Toolbar,
  Typography,
  Drawer,
  List,
  ListItem,
  ListItemIcon,
  ListItemText,
  Container,
  Box,
  Card,
  CardContent,
  Grid,
  IconButton,
} from '@mui/material';
import {
  Dashboard as DashboardIcon,
  People as PeopleIcon,
  Settings as SettingsIcon,
  Menu as MenuIcon,
} from '@mui/icons-material';

const drawerWidth = 240;

function Dashboard() {
  return (
    <Box sx={{ display: 'flex' }}>
      <AppBar position="fixed" sx={{ zIndex: 1201 }}>
        <Toolbar>
          <IconButton color="inherit" edge="start" sx={{ mr: 2 }}>
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            管理后台
          </Typography>
        </Toolbar>
      </AppBar>

      <Drawer
        variant="permanent"
        sx={{
          width: drawerWidth,
          flexShrink: 0,
          '& .MuiDrawer-paper': { width: drawerWidth, boxSizing: 'border-box' },
        }}
      >
        <Toolbar />
        <List>
          <ListItem button>
            <ListItemIcon><DashboardIcon /></ListItemIcon>
            <ListItemText primary="仪表板" />
          </ListItem>
          <ListItem button>
            <ListItemIcon><PeopleIcon /></ListItemIcon>
            <ListItemText primary="用户管理" />
          </ListItem>
          <ListItem button>
            <ListItemIcon><SettingsIcon /></ListItemIcon>
            <ListItemText primary="设置" />
          </ListItem>
        </List>
      </Drawer>

      <Box component="main" sx={{ flexGrow: 1, p: 3 }}>
        <Toolbar />
        <Container maxWidth="lg">
          <Grid container spacing={3}>
            <Grid item xs={12} md={4}>
              <Card>
                <CardContent>
                  <Typography color="textSecondary" gutterBottom>
                    总用户
                  </Typography>
                  <Typography variant="h4">1,234</Typography>
                </CardContent>
              </Card>
            </Grid>
            <Grid item xs={12} md={4}>
              <Card>
                <CardContent>
                  <Typography color="textSecondary" gutterBottom>
                    活跃用户
                  </Typography>
                  <Typography variant="h4">856</Typography>
                </CardContent>
              </Card>
            </Grid>
            <Grid item xs={12} md={4}>
              <Card>
                <CardContent>
                  <Typography color="textSecondary" gutterBottom>
                    新增用户
                  </Typography>
                  <Typography variant="h4">128</Typography>
                </CardContent>
              </Card>
            </Grid>
          </Grid>
        </Container>
      </Box>
    </Box>
  );
}

export default Dashboard;

下一步 #

现在你已经掌握了 MUI 的基础用法,继续学习 主题基础,深入了解如何定制你的应用主题!

最后更新:2026-03-28