首页
/ Material UI June 2019 更新详解:ButtonGroup、支持范围值的 Slider 与 TextareaAutosize 组件演进

Material UI June 2019 更新详解:ButtonGroup、支持范围值的 Slider 与 TextareaAutosize 组件演进

2026-09-07 10:53:52作者:钟日瑜

2019 年 6 月,Material UI(现位于仓库 material-ui)发布了一轮高频更新,核心成果是三个组件级里程碑:全新的 ButtonGroup 组件、被重构并加入范围(range)选择支持、且从 lab 迁入核心的 Slider,以及全新的 TextareaAutosize 组件。这篇文章以当时的官方月报(docs/pages/blog/june-2019-update.md)为主线,结合当前仓库中 packages/mui-material/src 下的真实源码与 docs/data/material/components 中的配套文档,回顾这三个组件"从发布到实现"的关键设计,并给出可直接复制运行的用法示例,帮助你理解这类高频交互组件在 Material UI 中是如何设计与演进的。

6 月更新背景:一次高速迭代的快照

月报在列举新功能时给出了一组当年 6 月的开发规模数据:当月共合并了来自 71 位贡献者的 198 个提交,改动 5,384 个文件,包含 26,199 行新增与 18,097 行删除。这些数字来自原文档本身,是了解该版本迭代密度的一手参考。

在功能层面,这轮更新的"重头戏"集中在表单与操作控件上:

  • 💄 引入全新的 ButtonGroup 组件;
  • 💄 Slider 组件被重构增强,加入范围选择能力,并从 lab 移入核心包(意味着成为官方稳定 API);
  • 💄 引入全新的 TextareaAutosize 组件。

月报原文档还指出"这份摘要只是冰山一角"——这正是 Material UI 典型的按月滚动发布节奏。下面逐一拆解这三个组件的设计要点与实现证据。

ButtonGroup:把相关按钮组织成一个整体

组件定位与基本用法

从当时的月报看,ButtonGroup 是本月"从无到有"的全新组件。它在文档中定位为"用于对相关按钮分组":

The ButtonGroup component can be used to group related buttons.

当前文档(docs/data/material/components/button-group/button-group.md)进一步明确了使用约束:需要分组的按钮必须作为 ButtonGroup 的直接子元素(immediate children),组件会负责处理相邻按钮间的圆角合并、边框消除和分组样式。典型用法如下:

import * as React from 'react';
import Button from '@mui/material/Button';
import ButtonGroup from '@mui/material/ButtonGroup';

export default function BasicButtonGroup() {
  return (
    <ButtonGroup variant="contained" aria-label="Basic button group">
      <Button>One</Button>
      <Button>Two</Button>
      <Button>Three</Button>
    </ButtonGroup>
  );
}

支持的外观与行为维度

结合当前官方文档,ButtonGroup 覆盖了几类高频定制诉求:

  • 变体(variant):支持 textcontainedoutlined 等标准按钮变体,可直接在 ButtonGroup 上统一下发(对应文档 Demo VariantButtonGroup.js);
  • 尺寸与颜色(size / color):通过 sizecolor 统一控制组内按钮外观(GroupSizesColors.js);
  • 纵向布局:设置 orientation="vertical" 可将按钮组从横排切换为竖排(GroupOrientation.js);
  • 去掉阴影disableElevation 可移除凸起阴影,更适配扁平化工具栏场景(DisableElevation.js);
  • 分离按钮(Split Button):ButtonGroup 常与下拉菜单组合成"分离按钮",主按钮直接触发动作、附按钮展开更多选项(SplitButton.js);
  • 加载态:得益于组内 Button 的 loading prop,按钮组也能呈现加载禁用状态(LoadingButtonGroup.js)。

源码中的分组机制

从源码结构看,ButtonGroup 的实现并非简单包一层容器:packages/mui-material/src/ButtonGroup/ButtonGroup.js 是组件主体,而样式/行为分组依赖两个上下文对象——ButtonGroupContext.tsButtonGroupButtonContext.ts

可以推断其内部流程是:ButtonGroup 先通过 React Context 向下分发"统一配置"(变体、颜色、尺寸、禁用焦点涟漪等),子级 Button 再通过 useButtonGroup 之类的读取逻辑感知自己"处于分组之中",从而自动调整圆角与边框——这解释了为什么"直接子元素"的约束会如此严格:只有处于 Context 树内的 Button 才会收到分组样式标记。分类常量与 CSS 类名则集中在 buttonGroupClasses.ts,文档示例与单元测试(ButtonGroup.test.js)共同保证了 API 的向后兼容。

Slider 重构:范围(Range)支持与 lab → core 的迁移

为什么这次重构值得关注

月报对 Slider 的描述是"被彻底重构与增强(overhauled and enhanced)",两个关键点分别是:

  1. 新增范围选择能力——可以用一个滑块同时设定区间的起点与终点;
  2. 从 lab 迁入核心——对 Material UI 而言,组件离开 @material-ui/lab 进入核心包意味着 API 正式稳定,可被生产环境放心依赖。

今天在仓库中,Slider 的实现位于核心包 packages/mui-material/src/Slider/Slider.js,其完整使用文档见 docs/data/material/components/slider/slider.md

范围滑块的经典实现

文档中体现"范围支持"最直观的示例是 RangeSlider.js,其核心思路是:value 传入一个二元数组,组件即进入范围模式:

import * as React from 'react';
import Box from '@mui/material/Box';
import Slider from '@mui/material/Slider';

function valuetext(value) {
  return `${value}°C`;
}

export default function RangeSlider() {
  const [value, setValue] = React.useState([20, 37]);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  return (
    <Box sx={{ width: 300 }}>
      <Slider
        getAriaLabel={() => 'Temperature range'}
        value={value}
        onChange={handleChange}
        valueLabelDisplay="auto"
        getAriaValueText={valuetext}
      />
    </Box>
  );
}

可以看到,范围模式与单值模式共用同一套 value / onChange 契约:单值时传 number,范围时传 [number, number],组件会自动渲染双滑块(thumb)与高亮区间轨道。

从当前文档看 Slider 的能力全景

围绕这次重构后的组件,当前官方文档沉淀出相当完整的使用矩阵:

  • 连续滑块:适合音量、亮度这类"主观取值"场景(默认行为);
  • 小尺寸:通过 size="small" 获得紧凑滑块;
  • 离散滑块与步进marks 可生成刻度标记;step 控制步长。文档特别提醒:自定义步长时,应把 shiftStep(Page Up/Down 或 Shift+方向键的步进粒度)调整为 step 的整数倍,以保证键盘操作语义一致;
  • 自定义刻度marks 支持传入富数组(每项含 value/label)来精确定位刻度位置;
  • 限制可选值step={null} 会把可选值严格限制在 marks 给出的集合内;
  • 常显数值标签valueLabelDisplay="on" 可让滑块上方的数值气泡始终可见(默认 "auto" 仅在拖拽/聚焦时显示);
  • 范围模式进阶disableSwap 用于禁止在拖拽一个滑块时自动切换到被鼠标悬停的另一个滑块;若希望在触碰最小间距时整段区间联动平移,可利用 onChange 回调中的 activeThumb 参数区分"当前拖动的是哪一个滑块";
  • 无轨道 / 反向轨道track={false} 隐藏轨道,track="inverted" 反向高亮;
  • 垂直滑块orientation="vertical" 让滑块沿垂直方向拖动;
  • 非线性刻度scale prop 允许对数值做非线性映射(官方示例用 value 代表 2^value),适合指数型取值范围。

源码层面的"重构痕迹"

从源码结构看,Slider 的复杂交互逻辑(指针/键盘/多点触控、步进与取值钳制)被抽取到了 useSlider.ts 这一个独立 hook 中,配套的类型声明位于 useSlider.types.ts,并且有独立的单元测试 useSlider.test.js。这种"状态逻辑抽 hook、视觉层独立成组件"的写法,正是那轮重构为后续可维护性打下的基础——组件主体(Slider.js)只负责把 hook 返回的状态渲染成符合 WAI-ARIA slider/multithumb 模式的 DOM。

关于可访问性,当前文档(slider.md)也给出了明确要求:每个滑块都需要可读的标签(通过 aria-labelaria-labelledbygetAriaLabel),并最好提供语义化的当前值描述(getAriaValueTextaria-valuetext)。这套规范与 WAI-ARIA APG 的多滑块模式对齐,也是组件在跨浏览器、跨读屏环境下可靠工作的基础。

TextareaAutosize:自动增高文本域

组件定位

月报中介绍的第三个新组件是 TextareaAutosize。它是对原生 <textarea> 的替换型工具组件,核心价值在于:高度会随内容与窗口尺寸变化自动伸缩,省去手写 auto-grow 脚本的麻烦。官方描述为:

The Textarea Autosize component automatically adjusts its height to match the length of the content within.

当前文档见 docs/data/material/components/textarea-autosize/textarea-autosize.md,其中说明:组件高度会响应键盘输入与窗口 resize 事件自动调整;默认情况下空内容渲染为单行。

导入与两个核心 props

import TextareaAutosize from '@mui/material/TextareaAutosize';

组件以 minRowsmaxRows 两个 prop 控制伸缩边界,这一点沿用了原 lab 时代的 API 设计,也是文档明确的两大基础场景:

// 最小高度:至少占 3 行
<TextareaAutosize
  minRows={3}
  aria-label="minimum height"
  placeholder="Minimum 3 rows"
/>

// 最大高度:超过 5 行后出现内部滚动而不是无限增高
<TextareaAutosize
  maxRows={5}
  aria-label="maximum height"
  placeholder="Maximum 5 rows"
/>

minRows 决定初始/最小展示行数(空组件默认约 1 行);maxRows 决定高度增长上限,文本继续增多时组件停止增高、由内容区产生滚动。二者配合即可覆盖从"单行输入框"到"受约束的评论框"的常见布局。

仓库中的实现位于核心包 packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx,类型声明见 TextareaAutosize.types.ts,配套交互/渲染测试见 TextareaAutosize.test.tsx

月报中的 7 月路线图:Tree View 与 Rating 的结局

原文档最后披露了 2019 年 7 月的路线图意图(并注明"会尽力,但不作保证"):

  • 继续开发 Tree View(树形视图) 组件;
  • 开发全新的 Rating(评分) 组件;
  • 同时向社区征集点赞排序的需求,以便按 👍 数决定优先级。

用当前仓库"回头看"这两个路线图项,可以得到清晰的落点:Rating 如今已是核心包中的成熟组件,其完整使用文档保留在 docs/data/material/components/rating;而 Tree View 后续被移交给了 MUI X 产品线,不再随 MUI Core 发布,这一演进过程在仓库博客 docs/pages/blog/lab-tree-view-to-mui-x.md 中有专门说明。对照可见:月报"预览 → 正式发布 → 视生态归属调整产品线"的路径,本身就是了解 MUI 组件生命周期管理的一个很好的样本。

小结

从 2019 年 6 月的这期月报可以提炼出 Material UI 组件演进的几条规律:

  1. 稳定化优先Slider 从 lab 迁入 core 标志着 API 冻结承诺,范围值通过"扩展 value 类型而非新增组件"完成,保持了组件表面一致性;
  2. 文档即规范:三个组件都沉淀了完整文档与大量可运行示例,ButtonGroupSliderTextareaAutosize 的使用矩阵至今仍是参考首选;
  3. 源码分层清晰:复杂交互抽成可独立测试的 hook(如 useSlider.ts)、分组联动依赖 Context(如 ButtonGroupContext.ts),是组件长期可维护的关键。

如果你想逐行核对上述实现,原始月报文件为 docs/pages/blog/june-2019-update.md,渲染入口是 docs/pages/blog/june-2019-update.js;三个组件的源码目录分别在 packages/mui-material/src/ButtonGrouppackages/mui-material/src/Sliderpackages/mui-material/src/TextareaAutosize

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.79 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
390