Material UI 2019 年 7 月更新全解读:Tree View、纵向 Tabs、Rating 与顶层导入 Codemod
本文基于仓库内官方发布日志 july-2019-update.md(发布于 2019-08-04,作者 Olivier Tassinari,标签为 Company)展开。该文档记录了 Material UI(当时仍处于 v4 时代)在 2019 年 7 月落地的一批关键功能:实验室新增 Tree View 与 Rating 组件、Tabs 支持纵向布局、推出迁移到顶层导入的 codemod,以及 8 月的开发路线图。阅读本文后,你将掌握这些能力的历史背景、它们在本仓库中对应的源码与文档位置、如何在实际代码中复现这些用法,以及它们如何演化为今天的推荐实践。
一、本季度更新概览:一次从组件到工程化的整体推进
按原文口径,2019 年 7 月的更新可以归纳为四个核心变化,全部围绕"扩展可用组件 + 改善使用体验 + 降低工程成本"展开:
- 在实验性组件库(the lab)中新增 Tree View 树形视图组件;
- 为 Tabs 增加
orientation="vertical",支持垂直方向的标签页布局; - 推出 codemod,帮助开发者一键迁移到顶层导入(top-level imports);
- 在实验性组件库中新增 Rating 评分组件。
发布日志同时给出了一组反映社区参与度的数据:7 月累计接受 146 个 commit,来自 54 位贡献者,共修改 2,004 个文件,新增 29,022 行、删除 25,455 行。这些数字说明当时的迭代节奏——功能上新之外,还有大量重构与清理工作同时进行。
需要先说明的是:这篇日志是 2019 年时间点的快照。文中提到的组件此后经历了一轮"从 lab 走向主包"的晋级,因此下文在讲解每个功能时会同时给出历史语境和仓库当前结构中的实际落点。
二、Tree View:首个树形视图组件进入实验室
7 月更新中最重要的新增组件之一便是 Tree View。原文把它定位为实验性能力,放入了组件实验室(lab)中,并附有一段演示动画(视频源文件至今仍保留在仓库静态资源目录 tree-view.mp4,由于格式限制,此处不以内嵌视频展示)。
从仓库当前源码结构看,Tree View 的实现保存在实验包中:
- TreeView 源码目录:提供树形容器本身,负责折叠 / 展开状态管理与节点导航;
- TreeItem 源码目录:对应树中的单个节点条目。
从源码结构可以推断,这一设计的初衷是把"树形展开/收起"这类通用逻辑沉淀成可控的容器组件,让使用者通过组合 TreeView 与 TreeItem 来声明式地描述层级数据,而不是手写递归渲染。这也是 lab 组件的一贯定位:先在小范围内验证 API 形态,再根据真实反馈决定是否晋级到主包。
需要留意的是,发布日志原文中的功能入口(/x/react-tree-view/)如今已指向 MUI X 产品线下的 Tree View 文档页;也就是说,这一能力后来从 lab 走出了独立的演进路线。对仍在使用 lab 版本的应用而言,本仓库的 TreeView 与 TreeItem 源码仍是可查证的一手实现参考。
三、垂直 Tabs:一个 orientation 属性解锁的布局形态
7 月同步为 Tabs 增加了垂直排列能力,即标签栏从横向平铺变为侧边竖排。这在"导航 + 内容面板"的经典后台布局中非常常见:左侧纵向菜单,右侧展示对应面板内容。
3.1 核心 API:orientation="vertical"
相关文档章节位于 tabs.md 的 Vertical tabs 小节。原文明确指出:"To make vertical tabs instead of default horizontal ones, there is orientation=\"vertical\""——即只需在 Tabs 上声明 orientation="vertical",即可由横向切换为纵向。文档同时补充了一条细节:纵向场景下滚动条默认被隐藏,可通过 visibleScrollbar 恢复。
3.2 完整可运行的官方示例
仓库在 docs/data/material/components/tabs/VerticalTabs.js 保留了该形态的官方演示,其关键结构如下(基于 hooks 与最新 API 编写):
function a11yProps(index) {
return {
id: `vertical-tab-${index}`,
'aria-controls': `vertical-tabpanel-${index}`,
};
}
<Box sx={{ flexGrow: 1, bgcolor: 'background.paper', display: 'flex', height: 224 }}>
<Tabs
orientation="vertical"
variant="scrollable"
value={value}
onChange={handleChange}
aria-label="Vertical tabs example"
sx={{ borderRight: 1, borderColor: 'divider' }}
>
<Tab label="Item One" {...a11yProps(0)} />
{/* ...更多 Tab */}
</Tabs>
<TabPanel value={value} index={0}>
Item One
</TabPanel>
</Box>
示例中有几个值得复刻的工程细节:
- 外层布局:用
Box以display: 'flex'横向排列"标签列 + 面板区",并用borderRight与borderColor: 'divider'在标签列右侧画一条分隔线,视觉上强化"菜单 / 内容"的左右关系; - 滚动策略:由于纵向排列空间有限,同时声明
variant="scrollable",配合.visibleScrollbar可自定义滚动条行为; - 无障碍约定:
a11yProps(index)统一生成id与aria-controls,用于把每个Tab按钮与对应role="tabpanel"的面板关联起来,属于 WAI-ARIA Tabs 模式的基础要求。这一点同样在 tabs.md 的 Accessibility 章节 中有完整说明。
以下是该小节对应的效果截图(源自本仓库发布日志素材):
四、顶层导入 Codemod:把深路径导入改造成 @mui/material
7 月更新带来的第三项能力属于工程效率范畴:一套用于迁移到顶层导入的 codemod。原文给出的目标形态非常直观:
import { Button, TextField } from '@mui/material';
4.1 背景:为什么需要"顶层导入"
在 v4 早期,社区广泛使用"深路径"写法,例如 import Button from '@material-ui/core/Button'。它的好处是兼容当时的打包工具,但坏处是每个组件都要单独写一行导入、模块路径冗长、难以统一审计。Material UI 的维护者随后决定支持顶层导入——由包根入口统一 export 全部组件,让消费者可以一次导入多个组件,同时也依赖现代打包器的 tree-shaking 能力在产物构建时剔除未使用代码。
4.2 Codemod 在仓库中的实现证据
这套迁移工具的真实实现至今仍保留在仓库中,位于 packages/mui-codemod/src/v4.0.0/top-level-imports.js。从源码可以看到其工作原理:
- 用正则
^@material-ui/core/(?:[^/]+/)*([^/]+)$匹配所有深路径导入声明; - 通过
require(importModule)得到主包导出的白名单(whitelist),用于校验每个导入名是否为合法导出; - 跳过
internal/等私有路径; - 将多个分散的深路径导入合并成一条来自主包的顶层导入语句。
也就是说,它把一段"逐组件导入"的代码,改写成发布日志示例中的聚合写法。针对这套转换,仓库还保留了端到端测试夹具(见 top-level-imports.test.js 及其 actual.js / expected.js 用例),验证了转换结果的正确性,并额外断言转换是幂等的(对已转换代码再次运行不会产生二次改动)。这说明 codemod 的定位是"一次性、可重复执行"的迁移工具。
4.3 工程实践的另一面:开发期的包体积与性能
发布日志专门引导读者阅读 Minimizing Bundle Size 指南,学习正确的工程配置。今天的这份指南给出了更完整的判断标准,值得展开说明:
- 生产构建:现代打包器(Webpack、Rollup、esbuild 等)本身会 tree-shake,因此顶层命名导入在产物中不会带来冗余代码;
- 开发构建:真正的性能开销发生在开发期——从
@mui/material这类"桶文件(barrel)"导入会让启动与热更新明显变慢。指南特别点名@mui/icons-material,其命名导入在开发期可能比按路径导入慢数倍; - 推荐写法:生产追求简洁、开发追求速度的折中方案是按子路径导入,例如:
// ✅ 推荐
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
// ❌ 开发期更慢
import { Button, TextField } from '@mui/material';
- 配套自动化:仓库在同目录下还提供了与历史 codemod 方向相反的工具——packages/mui-codemod/src/v5.0.0/path-imports.js。它的正则
^@mui/([^/]+)$专门识别来自@mui/material、@mui/icons-material的顶层桶导入,并把它们拆回各自对应的子路径导入,执行方式与指南文档一致:
npx @mui/codemod@latest v5.0.0/path-imports <path>
- ESLint 约束:为防止团队代码重新混入桶导入,指南建议配置
no-restricted-imports,禁止形如^@mui/[^/]+$的顶层导入模式; - 编辑器约束:对 VS Code 用户,指南还给出了
typescript.preferences.autoImportSpecifierExcludeRegexes: ["^@mui/[^/]+$"]的配置,让自动补全不再从桶文件引入 import。
这段"顶层导入(2019 年提出)→ 深路径导入回归(面向开发期性能)"的演进,恰好解释了为什么今天的仓库中会同时保留 v4.0.0/top-level-imports 与 v5.0.0/path-imports 两套方向相反的工具。
五、Rating 评分组件:实验室里的新面孔
7 月更新的第四个新增组件是 Rating。发布日志同样把它定位在实验包中,并配有效果截图。评分组件面向"打分"型交互,例如内容评价、星级反馈等,属于 Web 应用中的高频控件,填补了当时组件体系的一个空缺。
从仓库当前结构看,Rating 已完成从实验包到主包的晋级——实现位于 packages/mui-material/src/Rating/Rating.js(连同配套的类型声明与 ratingClasses.ts),这说明它的 API 经过 lab 期的验证后被正式纳入主包长期维护。
其配套文档与演示集中在 docs/data/material/components/rating 目录,主文档为 rating.md。从该目录的 demo 文件即可看出它覆盖的交互能力相当完整:
- BasicRating.js:最基础的受控 / 非受控用法;
- HalfRating.js:半星(小数)精度;
- HoverRating.js:悬停即时反馈 + 选中后落定;
- CustomizedRating.js:通过
icon/emptyIcon替换默认星级图标; - RatingSize.js:尺寸随
size或主题缩放; - RadioGroupRating.js 与 TextRating.js:展示如何与无障碍语义、自定义文本评分结合。
对需要接入评分的开发者,可以依据上述 demo 按需挑选对应形态,并到 rating.md 查阅完整的 props 与无障碍说明。
六、8 月路线图:Autocomplete、Skeleton 与社区投票
发布日志除了回顾 7 月成果,也公开了 8 月的开发意图(原文明确标注"我们会尽力,但不作保证"):
- 更完善的输入类组件:准备推出开箱即用的 Autocomplete(自动补全)、Combo Box(组合框)与 Multi-select(多选)组件。这一方向此后落地为功能完备的
Autocomplete,并成为 Material UI 使用率极高的组件之一; - Skeleton 骨架屏:继续推进新组件,并开放了可预览版本。当时预览链接指向临时的 deploy preview 站点,如今从仓库结构看,Skeleton 已正式进入主包,实现在 packages/mui-material/src/Skeleton/Skeleton.js,用于在数据加载期间展示占位形状、缓解白屏焦虑;
- 社区投票机制:日志最后邀请使用者去为 GitHub issue 点赞投票,因为点赞数(👍)直接影响维护团队的优先级排序。这条"以社区信号驱动路线图"的工作方式,与发布日志开头列出的 54 位贡献者、146 个 commit 一起,勾勒出 Material UI 开源协作的真实运行模式。
七、总结:从一份月度日志回看组件库的演进方法论
回顾 july-2019-update.md 这份 2019 年 7 月的月度日志,可以看到一套清晰可复用的演进方法论:
- 新组件先在 lab 试水:Tree View、Rating(以及路线图中的 Skeleton)都先以实验组件形态发布,用真实使用反馈检验 API 设计,成熟后再晋级主包;
- 一次更新同时解决"用起来"与"引起来"两类问题:横向看,新增组件解决功能缺口,codemod 与包体积指南解决工程实践缺口,二者共同降低使用门槛;
- 文档即证据:每个新能力都同步沉淀了可运行的 demo、源码与指南(对应 docs/data/material/components 下的各组件目录),并配套 codemod 测试夹具保证迁移结果可验证;
- 路线图保持开放:优先级由社区投票驱动,功能内容随真实需求滚动调整。
对照今天的仓库结构,"Tree View 交给 MUI X 独立演进、Rating 与 Skeleton 进入 mui-material 主包、顶层导入在开发期被重新评估为按路径导入"这些后续走向,恰好都印证了当时这套以 lab 验证 + 工程配套 + 数据反馈为核心的迭代模式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0625
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


