Material UI v4 发布 🎉
React 组件,用于更快更简单的 Web 开发。构建您自己的设计系统,或从 Material Design 开始。
Material UI v4 终于发布了。我们对这次发布感到非常兴奋,因为它为 UI 组件定义了更好的基础。感谢所有人,特别是团队,以及所有贡献代码、问题分类和支持的人。谢谢你们。
✨✨✨ 请查看 GitHub 上的 4.0.0 发行说明。✨✨✨
https://mui.org.cn/
摘要
v4 的高层次目标
Material UI v1 在一年前发布。版本 4 是自那时以来我们最重要的主要版本。对于那些不熟悉项目历史的人来说,我们没有发布 v2,而 v3 仅引入了轻微的浏览器支持更改。
此版本在我们固定的频率发布策略中发布。我们尝试至少每 12 个月发布一个主要版本,最多每 6 个月发布一个。从 v0 到 v1 的迁移很痛苦,感觉就像使用了两个不同的 UI 库。我们已尽最大努力最大限度地减少从 v3 迁移到 v4 所需的时间。为了帮助简化过渡,您可以遵循此迁移指南📚。它不应超过几个小时。
此版本受到两个主要因素的影响。首先,根据我们在 3 月份进行的开发者调查,我们分析了结果,并使用它们来更改我们来年的优先级。其次,我们需要与 React 社区和 Material Design 规范中的最新最佳实践保持同步。
自定义
Google 的 Material Design 团队已将设计系统框架的自定义作为核心功能:Material Theming。这对我们来说是库的一个重要维度。自 v1 发布以来,我们一直在改进组件自定义演示,一个版本接一个版本。我们展示了各种不同的设计
在听取了数百名开发者关于 v3 自定义体验的意见后,我们意识到我们可以做得更好。我们发现了 4 类常见问题。
- CSS 特异性。开发者的样式特异性需要更高,才能胜过 Material UI 在页面中注入的样式。默认情况下,Material UI 在
<head>
元素的末尾注入其样式。但是,样式化组件和其他流行的样式解决方案会在其之前注入样式,从而失去特异性。为了解决这个问题,我们引入了一个新的 prop:injectFirst
。
import { StylesProvider } from '@mui/styles';
<StylesProvider injectFirst>
{/* Your component tree.
Styled components can override Material UI's styles. */}
</StylesProvider>;
使用 injectFirst 后的 DOM 输出。
- 类名样板代码。在 v1 努力的早期,我们决定使用 CSS-in-JS 样式解决方案:JSS。绝大多数 CSS-in-JS 解决方案输出非确定性类名,例如
.fHmkjM
。此设计决策有助于隔离每个组件的样式,但是,它使覆盖变得更加困难。我们在 v1 中引入了classes
API,旨在针对我们所有的元素,以减轻此问题。我们已经观察了此 API 的使用情况数月,并看到许多人为此苦苦挣扎。在正确的元素上应用类名可能具有挑战性,并且也需要样板代码。为了进一步改善这种情况,我们将类名生成更改为输出全局类名,同时保持classes
API 像以前一样工作💅。
并排比较有效的类名与全局方法。
⚠️ 使用全局类名可提供更多功能,但也带来责任。我们鼓励使用增加自定义样式隔离的模式。
- 伪类。 伪类是添加到选择器的关键字,用于指定所选元素的特殊状态。原生元素支持各种伪类,最受欢迎的伪类是:
:focus
、:hover
、:active
。有时,Material UI 无法使用伪类,因为平台中不存在该状态,例如菜单项的选定状态。Material UI 实现了对八种不同自定义伪类的支持。重要的是要理解,当使用伪类时,您需要增加特异性。例如
.MenuItem {
color: black;
}
/* We increase the specificity */
.MenuItem.Mui-selected {
color: blue;
}
- 动态变化。 作为最受要求的功能之一,我们添加了对样式函数的支持
const useStyles = makeStyles({
// style rule
foo: (props) => ({
backgroundColor: props.backgroundColor,
}),
bar: {
// CSS property
color: (props) => props.color,
},
});
function MyComponent() {
// Simulated props for the purpose of the example
const props = {
backgroundColor: 'black',
color: 'white',
};
// Pass the props as the first argument of useStyles()
const classes = useStyles(props);
return <div className={`${classes.foo} ${classes.bar}`} />;
}
文档
在开发者调查中,文档被报告为第三大关键痛点。我们已经修复了一些报告的问题,并旨在不断改进。
- TypeScript。TypeScript 的增长令人印象深刻,其文档网站的流量在 3 年内增长了 6 倍。Material UI v1 发布时带有内置的 TypeScript 定义,但我们需要做更多的事情。Sebastian 领导了将所有演示从 JavaScript 迁移到 TypeScript 的工作。这有两个重要的含义。首先,我们对演示进行类型检查,这大大提高了我们的 TypeScript 测试覆盖率。我们在迁移过程中修复了许多问题。其次,如果您正在使用 TypeScript 编写应用程序,您可以直接复制粘贴我们的演示,而无需转换它们,也无需修复晦涩的错误。
https://typescript.net.cn 流量随时间推移的估计。
使用 JS/TS 开关以 JavaScript 或 TypeScript 查看代码
i18n。开发者来自世界各地访问 Material UI 的文档。我们希望尽可能多地包括人们🌎🌍🌏。我们完成了在 v3 中开始的工作,即处理 Algolia 搜索支持、Google 搜索索引、目录和侧边导航基础设施。
我们要感谢 Danica Shen、Dominik Engel 和 Jairon Alves Lima 在 🇨🇳、🇩🇪 和 🇧🇷 翻译方面做出的英勇工作,同时也不要忘记其他 348 位(并且还在增长)翻译人员。
最佳实践。我们现在建议尽可能使用 hooks API 而不是 classes API。我们已经迁移了大部分演示,以展示单一方法。
更好的 UX。我们更改了菜单组织,以将所有组件分组在单个导航项下。我们已将背景颜色更改为白色,以增加文本对比度和可读性。
性能
您可能会担心使用 Material UI 的组件会使您的网站/应用程序臃肿并减慢速度。您自己编写组件会更好吗?嗯,我们的使命是使这种成本尽可能小🚀。
- Tree shaking。Material UI v4 是第一个支持使用 ES 模块进行原生 tree shaking 的版本。这有一个重要的 DX 好处——您现在可以在导入多个组件时使用解构导入
import {
Table
TableBody,
TableCell,
TableHead,
TableRow,
Paper,
} from '@mui/material';
- 捆绑包大小减小。在最后一个 v3 版本和第一个 v4 beta 版本之间,捆绑包大小从 95 kB gzipped 降至 80 kB gzipped 以下。考虑到我们在此过程中添加了新功能和组件😍,这真是非凡的!这得益于许多小的增量更改:tree shaking、删除多个 内部依赖项、hooks 迁移、clsx 迁移、智能 Babel 插件等。
捆绑包大小减少了 -15%。⚠️ 请不要使用绝对数字来比较不同的 UI 库。没有人应该导入整个 barrel index.js 文件。重要的是您导入的单个模块的成本。
- 持续捆绑包大小跟踪。这种捆绑包大小的减少之所以成为可能,仅仅是因为我们在每个 pull request 中都跟踪此指标。我们改进了我们的策略,从 size-limit 转向 React 启发的解决方案。
精细级别跟踪
- Preact X。 我们引入了一个可用的 与 Preact 的集成示例。Preact 是 React 的快速、小 1/10 的替代品,具有相同的现代 API。我们将尽力支持它。
- 运行时性能。我们听说有些人在使用 Material UI 的运行时成本方面遇到了困难。我们解决了一些报告的问题,但没有系统性地解决。我们观察到通过从 classes API 迁移到 hooks API 略有提升。但是,由于我们缺乏适当设置的性能基准,因此很难取得进展。这是 v5 需要考虑的事情。
为未来做准备
Material UI v4 依赖于 React ≥16.8.0。这是第一个支持新的 Hooks API 的 React 版本。
- Ref 转发。大多数时候,您使用
ref
prop 来访问 React 元素的底层 DOM 节点。您可能想要聚焦元素、计算元素的位置等等。您永远不需要访问 Material UI 组件的实例方法,它们被认为是私有的。当真正需要时,组件会公开一个action
。例如,您可能希望在选项卡指示器位置与选项卡项位置失去同步时更新选项卡指示器位置。为了简化此用例,Sebastian 领导了一项工作,以实现React.forwardRef()
。在实践中,这意味着您可以像使用内置组件(button
、div
等)一样检索对 DOM 节点的引用。
import { Button } from '@mui/material';
function MyButton() {
const myRef = React.useRef();
return <Button ref={myRef}>;
}
Hooks 迁移。虽然 没有计划 从 React 中删除类,但 React 团队 鼓励 使用 hooks API 编写新代码。Josh 领导了一项工作,以使用 hooks API 重写我们的大部分组件。此更改有几个优点。
并非所有我们支持的平台都可以原生使用 class API,因此我们使用 Babel 转译语法。函数在任何地方都受支持,它们需要的代码行数更少。通过消除转译类的需求,我们观察到 gzipped 捆绑包减少了 -2%。
它减少了 React Dev Tools ⚛️ 中的噪音,因为我们可以将最常见情况下的中间元素数量从 5 个减少到 2 个。我们发现 hooks API 更易于使用:编写、阅读和更改。这对每个人的生产力都是净收益。开发者阅读我们的源代码以寻找灵感,因此我们应该尽力推广最佳模式。
生产中一个 Typography 元素的 React Dev Tools 输出(此 POC 可能会进一步改善情况)。
并发模式。React 分享了其 发布时间表,其中介绍了 React 中即将推出的重要功能。并发模式 应在未来几个月内发布。并发模式允许 React 应用程序通过在不阻塞主线程的情况下渲染组件树来提高响应速度。我们一直在努力为此做好准备。大部分工作都与修复 <React.StrictMode> 警告有关。您应该很快就能利用它🔥。
浅层测试。 我们已经删除了大部分内部浅层测试,转而依赖 完全挂载测试。
Material Design
我们的大多数用户对我们组件的美观功能方面感兴趣,而不是严格应用 Material Design 指南。但是,我们认为与指南保持同步对我们来说很重要。该规范自 Google 在 Google I/O 2018 中将其作为其应用程序的设计语言以来,收到了最重要的更新。
当我们发布 Material UI v1 时,Material Design “v2” 的发布让我们感到惊讶。从那时起,我们一直在努力升级我们的组件。在 v4 中,我们更新了 Tab、Snackbar、Checkboxes、Radios、Switches、List、Dialog 和其他组件的样式✨。
紧凑型轮廓文本字段
紧凑型填充文本字段
新功能是什么?
新事物太多了,我们无法详尽列举。除了我们已经宣布的内容之外,您还会发现
众多示例之一
Box 组件的应用示例。
新的间距助手 API 的示例。
- 由 Dmitriy Kovalenko 📅 创建和支持的新 @material-ui/pickers 包。
键盘支持
内联模式
- 新的 @mui/styles 包,隔离了我们的样式解决方案。它可以独立于核心组件使用。它带有一个需要较少样板代码的 hooks API 😍
import * as React from 'react';
import { makeStyles } from '@mui/material/styles';
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
},
});
export default function Hook() {
const classes = useStyles();
return <button className={classes.root}>Hook</button>;
}
⚠️ 请注意 @mui/styles 和 @mui/material/styles 之间的区别。后者包含默认主题。
下一步是什么?
我们共同完成了我们在一年前的 v1 版本博客文章中定义的大部分目标。我们为每一位贡献者感到自豪。我们将尝试以同样的规律执行这些新目标
- 更多组件。 这是迄今为止库中最受要求的改进维度。我们已经确定了一些我们有兴趣构建的有用组件
- 布局组件
- Autocomplete/ ComboBox / Dropdown List / MultiSelect
- 核心中的 Slider 以及对范围值的支持
- 树状视图
- Dropzone / Upload
- 骨架屏
- Jumbotron
- 轮播
- 评分
- 时间线
- 高级表格
请告诉我们您想要的组件!🚀
- 文档。文档至关重要。我们正在开发页面排名机制,这将帮助我们更好地确定文档工作的优先级。
- 在核心中使用
system
。 我们收到了关于新 system 包的良好反馈。展望未来,我们将尝试将其移至核心组件。理想情况下,您应该能够使用主题中的动态颜色和变体,并访问所有 props
import { Button } from '@mui/material';
<Button mt={{ xs: 2, md: 3 }}>Hello worlds</Button>;
- 样式化组件。 我们已经看到许多人要求迁移到样式化组件。我们希望 Material UI v5 能够更好地与社区最受欢迎的工具保持一致,但与此同时,我们不想破坏您的代码。因此,我们将致力于将组件与样式解决方案隔离。新的 @mui/styles 包是朝着这个方向迈出的第一步。我们设想一个世界,您可以使用使用样式化组件、linaria 和 JSS 或不使用任何样式进行样式化的 Material UI。开发者应该能够使用他们首选的样式解决方案,而无需支付两个 CSS-in-JS 运行时的成本。
- 可访问性。 虽然我们尝试修复用户报告的所有可访问性问题,但我们认为我们可以做得更好。我们希望对我们所有的组件进行专业的 ADA 审计♿️。
高级主题商店
我们将如何维持这个雄心勃勃的路线图?我们将遵循 Bootstrap 模型。我们正在开发高级主题商店。
我们已经与生态系统中最好的主题作者建立了合作伙伴关系。在几周内,您应该会找到最好的 Material UI 模板和主题的集合😍。
谢谢
最后,再次感谢每一位为 Material UI v4 做出贡献的人。我对这次发布感到非常兴奋!这仅仅是个开始。我们将继续努力交付尽可能最好的 React UI 框架组件。
您可以在 Medium 上找到相同的帖子。