Material-UI 输入组件 #

概述 #

MUI 提供了丰富的输入组件,用于构建交互式表单和用户界面。

text
输入组件体系
│
├── Button           按钮
├── ButtonGroup      按钮组
├── IconButton       图标按钮
├── TextField        文本输入框
├── Select           选择器
├── Checkbox         复选框
├── Radio            单选框
├── Switch           开关
├── Slider           滑块
├── Rating           评分
├── Autocomplete     自动完成
└── ToggleButton     切换按钮

Button 按钮 #

基础用法 #

jsx
import { Button, Stack } from '@mui/material';

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

颜色变体 #

jsx
<Stack spacing={2} direction="row">
  <Button color="primary">Primary</Button>
  <Button color="secondary">Secondary</Button>
  <Button color="success">Success</Button>
  <Button color="error">Error</Button>
  <Button color="info">Info</Button>
  <Button color="warning">Warning</Button>
</Stack>

尺寸 #

jsx
<Stack spacing={2} direction="row" alignItems="center">
  <Button size="small">Small</Button>
  <Button size="medium">Medium</Button>
  <Button size="large">Large</Button>
</Stack>

带图标 #

jsx
import { Delete as DeleteIcon, Send as SendIcon } from '@mui/icons-material';

<Stack spacing={2} direction="row">
  <Button variant="contained" startIcon={<DeleteIcon />}>
    删除
  </Button>
  <Button variant="contained" endIcon={<SendIcon />}>
    发送
  </Button>
</Stack>

图标按钮 #

jsx
import { IconButton } from '@mui/material';
import { Delete as DeleteIcon, Alarm as AlarmIcon, AddShoppingCart as AddShoppingCartIcon } from '@mui/icons-material';

<Stack direction="row" spacing={1}>
  <IconButton aria-label="delete">
    <DeleteIcon />
  </IconButton>
  <IconButton aria-label="delete" disabled color="primary">
    <DeleteIcon />
  </IconButton>
  <IconButton color="secondary" aria-label="add an alarm">
    <AlarmIcon />
  </IconButton>
  <IconButton color="primary" aria-label="add to shopping cart">
    <AddShoppingCartIcon />
  </IconButton>
</Stack>

加载状态 #

jsx
import { LoadingButton } from '@mui/lab';
import { Save as SaveIcon } from '@mui/icons-material';

<Stack direction="row" spacing={2}>
  <LoadingButton loading variant="outlined">
    提交
  </LoadingButton>
  <LoadingButton loading loadingIndicator="Loading..." variant="outlined">
    获取数据
  </LoadingButton>
  <LoadingButton
    loading
    loadingPosition="start"
    startIcon={<SaveIcon />}
    variant="outlined"
  >
    保存
  </LoadingButton>
</Stack>

按钮组 #

jsx
import { ButtonGroup } from '@mui/material';

<Stack spacing={2}>
  <ButtonGroup variant="contained" aria-label="Basic button group">
    <Button>一</Button>
    <Button>二</Button>
    <Button>三</Button>
  </ButtonGroup>

  <ButtonGroup variant="outlined" color="secondary">
    <Button>一</Button>
    <Button>二</Button>
    <Button>三</Button>
  </ButtonGroup>

  <ButtonGroup orientation="vertical" variant="text">
    <Button>上</Button>
    <Button>中</Button>
    <Button>下</Button>
  </ButtonGroup>
</Stack>

TextField 文本输入框 #

基础用法 #

jsx
import { TextField, Stack } from '@mui/material';

<Stack spacing={2}>
  <TextField id="outlined-basic" label="Outlined" variant="outlined" />
  <TextField id="filled-basic" label="Filled" variant="filled" />
  <TextField id="standard-basic" label="Standard" variant="standard" />
</Stack>

表单属性 #

jsx
<Stack spacing={2}>
  <TextField
    label="必填字段"
    required
  />
  <TextField
    label="禁用"
    disabled
  />
  <TextField
    label="只读"
    InputProps={{ readOnly: true }}
  />
  <TextField
    label="密码"
    type="password"
  />
  <TextField
    label="多行文本"
    multiline
    rows={4}
  />
</Stack>

验证状态 #

jsx
<Stack spacing={2}>
  <TextField
    error
    label="错误状态"
    helperText="请输入有效内容"
  />
  <TextField
    label="成功状态"
    color="success"
    helperText="输入正确"
  />
</Stack>

辅助文本 #

jsx
<TextField
  label="带帮助文本"
  helperText="这是一段帮助文本"
  fullWidth
/>

前缀和后缀 #

jsx
<Stack spacing={2}>
  <TextField
    label="金额"
    InputProps={{ startAdornment: <InputAdornment position="start">¥</InputAdornment> }}
  />
  <TextField
    label="重量"
    InputProps={{ endAdornment: <InputAdornment position="end">kg</InputAdornment> }}
  />
</Stack>

图标 #

jsx
import { AccountCircle, Lock } from '@mui/icons-material';

<Stack spacing={2}>
  <TextField
    label="用户名"
    InputProps={{ startAdornment: <AccountCircle sx={{ mr: 1, color: 'action.active' }} /> }}
  />
  <TextField
    label="密码"
    type="password"
    InputProps={{ endAdornment: <Lock sx={{ ml: 1, color: 'action.active' }} /> }}
  />
</Stack>

尺寸 #

jsx
<Stack spacing={2}>
  <TextField label="Small" size="small" />
  <TextField label="Medium" size="medium" />
</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>
  );
}

变体 #

jsx
<Stack spacing={2}>
  <FormControl variant="standard" fullWidth>
    <InputLabel>Standard</InputLabel>
    <Select value={age} label="Standard" onChange={handleChange}>
      <MenuItem value={10}>10</MenuItem>
      <MenuItem value={20}>20</MenuItem>
    </Select>
  </FormControl>

  <FormControl variant="filled" fullWidth>
    <InputLabel>Filled</InputLabel>
    <Select value={age} label="Filled" onChange={handleChange}>
      <MenuItem value={10}>10</MenuItem>
      <MenuItem value={20}>20</MenuItem>
    </Select>
  </FormControl>

  <FormControl variant="outlined" fullWidth>
    <InputLabel>Outlined</InputLabel>
    <Select value={age} label="Outlined" onChange={handleChange}>
      <MenuItem value={10}>10</MenuItem>
      <MenuItem value={20}>20</MenuItem>
    </Select>
  </FormControl>
</Stack>

多选 #

jsx
<FormControl fullWidth>
  <InputLabel>多选</InputLabel>
  <Select
    multiple
    value={names}
    onChange={handleChange}
    input={<OutlinedInput label="多选" />}
    renderValue={(selected) => selected.join(', ')}
  >
    {names.map((name) => (
      <MenuItem key={name} value={name}>
        <Checkbox checked={names.indexOf(name) > -1} />
        <ListItemText primary={name} />
      </MenuItem>
    ))}
  </Select>
</FormControl>

分组 #

jsx
<Select value={age} onChange={handleChange}>
  <ListSubheader>青年</ListSubheader>
  <MenuItem value={10}>10岁</MenuItem>
  <MenuItem value={20}>20岁</MenuItem>
  <ListSubheader>中年</ListSubheader>
  <MenuItem value={30}>30岁</MenuItem>
  <MenuItem value={40}>40岁</MenuItem>
</Select>

Checkbox 复选框 #

基础用法 #

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

<Stack>
  <FormControlLabel control={<Checkbox />} label="选项 1" />
  <FormControlLabel control={<Checkbox defaultChecked />} label="默认选中" />
  <FormControlLabel disabled control={<Checkbox />} label="禁用" />
</Stack>

颜色 #

jsx
<Stack direction="row">
  <Checkbox defaultChecked color="primary" />
  <Checkbox defaultChecked color="secondary" />
  <Checkbox defaultChecked color="success" />
  <Checkbox defaultChecked color="default" />
</Stack>

图标自定义 #

jsx
import { Favorite, FavoriteBorder } from '@mui/icons-material';

<FormControlLabel
  control={<Checkbox icon={<FavoriteBorder />} checkedIcon={<Favorite />} />}
  label="收藏"
/>

复选框组 #

jsx
function CheckboxGroup() {
  const [checked, setChecked] = useState([true, false]);

  const handleChange = (index) => (event) => {
    const newChecked = [...checked];
    newChecked[index] = event.target.checked;
    setChecked(newChecked);
  };

  return (
    <Stack>
      <FormControlLabel
        control={<Checkbox checked={checked[0]} onChange={handleChange(0)} />}
        label="选项 A"
      />
      <FormControlLabel
        control={<Checkbox checked={checked[1]} onChange={handleChange(1)} />}
        label="选项 B"
      />
    </Stack>
  );
}

Radio 单选框 #

基础用法 #

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

function RadioButtons() {
  const [value, setValue] = useState('female');

  return (
    <FormControl>
      <FormLabel>性别</FormLabel>
      <RadioGroup value={value} onChange={(e) => setValue(e.target.value)}>
        <FormControlLabel value="female" control={<Radio />} label="女" />
        <FormControlLabel value="male" control={<Radio />} label="男" />
        <FormControlLabel value="other" control={<Radio />} label="其他" />
      </RadioGroup>
    </FormControl>
  );
}

行排列 #

jsx
<RadioGroup row value={value} onChange={handleChange}>
  <FormControlLabel value="female" control={<Radio />} label="女" />
  <FormControlLabel value="male" control={<Radio />} label="男" />
</RadioGroup>

颜色 #

jsx
<Stack direction="row">
  <Radio checked color="primary" />
  <Radio checked color="secondary" />
  <Radio checked color="success" />
  <Radio checked color="default" />
</Stack>

Switch 开关 #

基础用法 #

jsx
import { Switch } from '@mui/material';

<Stack>
  <FormControlLabel control={<Switch />} label="开关" />
  <FormControlLabel control={<Switch defaultChecked />} label="默认开启" />
  <FormControlLabel disabled control={<Switch />} label="禁用" />
</Stack>

颜色 #

jsx
<Stack direction="row" spacing={1}>
  <Switch defaultChecked color="primary" />
  <Switch defaultChecked color="secondary" />
  <Switch defaultChecked color="default" />
</Stack>

尺寸 #

jsx
<Stack>
  <FormControlLabel control={<Switch size="small" />} label="Small" />
  <FormControlLabel control={<Switch size="medium" />} label="Medium" />
</Stack>

自定义图标 #

jsx
<Switch
  checked={checked}
  onChange={handleChange}
  icon={<WbSunny />}
  checkedIcon={<Brightness3 />}
/>

Slider 滑块 #

基础用法 #

jsx
import { Slider, Box } from '@mui/material';

<Stack spacing={2}>
  <Slider defaultValue={50} aria-label="Default" />
  <Slider defaultValue={50} valueLabelDisplay="auto" />
  <Slider defaultValue={50} disabled />
</Stack>

范围滑块 #

jsx
<Slider
  getAriaLabel={() => 'Temperature range'}
  value={value}
  onChange={handleChange}
  valueLabelDisplay="auto"
/>

离散滑块 #

jsx
<Slider
  aria-label="Temperature"
  defaultValue={30}
  valueLabelDisplay="auto"
  step={10}
  marks
  min={10}
  max={110}
/>

自定义标记 #

jsx
const marks = [
  { value: 0, label: '0°C' },
  { value: 20, label: '20°C' },
  { value: 37, label: '37°C' },
  { value: 100, label: '100°C' },
];

<Slider
  aria-label="Custom marks"
  defaultValue={20}
  step={10}
  marks={marks}
/>

Rating 评分 #

基础用法 #

jsx
import { Rating } from '@mui/material';

<Stack spacing={1}>
  <Rating name="half-rating" defaultValue={2.5} precision={0.5} />
  <Rating name="simple-controlled" value={value} onChange={(event, newValue) => setValue(newValue)} />
  <Rating name="read-only" value={value} readOnly />
  <Rating name="disabled" value={value} disabled />
</Stack>

自定义图标 #

jsx
<Rating
  name="customized-color"
  defaultValue={2}
  precision={0.5}
  icon={<Favorite fontSize="inherit" />}
  emptyIcon={<FavoriteBorder fontSize="inherit" />}
/>

带文字 #

jsx
<Box sx={{ display: 'flex', alignItems: 'center' }}>
  <Rating value={value} precision={0.5} />
  <Typography sx={{ ml: 2 }}>{value} 星</Typography>
</Box>

Autocomplete 自动完成 #

基础用法 #

jsx
import { Autocomplete, TextField } from '@mui/material';

const options = ['选项 1', '选项 2', '选项 3'];

<Autocomplete
  options={options}
  renderInput={(params) => <TextField {...params} label="选择选项" />}
/>

多选 #

jsx
<Autocomplete
  multiple
  options={top100Films}
  getOptionLabel={(option) => option.title}
  defaultValue={[top100Films[13]]}
  renderInput={(params) => (
    <TextField {...params} variant="standard" label="多选" />
  )}
/>

分组 #

jsx
<Autocomplete
  options={options.sort((a, b) => -b.firstLetter.localeCompare(a.firstLetter))}
  groupBy={(option) => option.firstLetter}
  getOptionLabel={(option) => option.title}
  renderInput={(params) => <TextField {...params} label="分组" />}
/>

表单实战示例 #

登录表单 #

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

function LoginForm() {
  return (
    <Box component="form" sx={{ maxWidth: 400, mx: 'auto', p: 3 }}>
      <Typography variant="h5" align="center" gutterBottom>
        登录
      </Typography>
      <TextField
        fullWidth
        label="邮箱"
        type="email"
        margin="normal"
        required
      />
      <TextField
        fullWidth
        label="密码"
        type="password"
        margin="normal"
        required
      />
      <FormControlLabel
        control={<Checkbox value="remember" color="primary" />}
        label="记住我"
      />
      <Button
        type="submit"
        fullWidth
        variant="contained"
        sx={{ mt: 3, mb: 2 }}
      >
        登录
      </Button>
      <Typography align="center">
        <Link href="#">忘记密码?</Link>
      </Typography>
    </Box>
  );
}

注册表单 #

jsx
function RegisterForm() {
  const [gender, setGender] = useState('');

  return (
    <Box component="form" sx={{ maxWidth: 500, mx: 'auto', p: 3 }}>
      <Typography variant="h5" gutterBottom>
        注册
      </Typography>
      <Grid container spacing={2}>
        <Grid item xs={12} sm={6}>
          <TextField fullWidth label="名" required />
        </Grid>
        <Grid item xs={12} sm={6}>
          <TextField fullWidth label="姓" required />
        </Grid>
        <Grid item xs={12}>
          <TextField fullWidth label="邮箱" type="email" required />
        </Grid>
        <Grid item xs={12}>
          <TextField fullWidth label="密码" type="password" required />
        </Grid>
        <Grid item xs={12}>
          <TextField fullWidth label="确认密码" type="password" required />
        </Grid>
        <Grid item xs={12}>
          <FormControl fullWidth>
            <InputLabel>性别</InputLabel>
            <Select value={gender} label="性别" onChange={(e) => setGender(e.target.value)}>
              <MenuItem value="male">男</MenuItem>
              <MenuItem value="female">女</MenuItem>
              <MenuItem value="other">其他</MenuItem>
            </Select>
          </FormControl>
        </Grid>
        <Grid item xs={12}>
          <FormControlLabel
            control={<Checkbox required />}
            label="我同意服务条款"
          />
        </Grid>
        <Grid item xs={12}>
          <Button type="submit" fullWidth variant="contained">
            注册
          </Button>
        </Grid>
      </Grid>
    </Box>
  );
}

下一步 #

继续学习 数据展示组件,了解表格、卡片等展示组件!

最后更新:2026-03-28