MDC-based Angular Material组件迁移
1. 前言
在 Angular Material v15 中,许多组件已基于官方的 Web Material Design Components (MDC) 进行了重构。 以下导入的组件已被重构:
Import path | Summary of changes |
---|---|
@angular/material/autocomplete | Style changes only |
@angular/material/button | Style changes, API changes |
@angular/material/card | Style changes only |
@angular/material/checkbox | Style changes, changes to event behavior |
@angular/material/chips | Complete rewrite |
@angular/material/core | Style changes only |
@angular/material/dialog | Style changes, changes to change detection behavior |
@angular/material/form-field | Style changes, some appearances removed, API changes |
@angular/material/input | Style changes only |
@angular/material/list | Style changes, API changes |
@angular/material/menu | Style changes, API changes |
@angular/material/paginator | Style changes only |
@angular/material/progress-bar | Style changes only |
@angular/material/progress-spinner | Style changes only |
@angular/material/radio | Style changes only |
@angular/material/select | Style changes only |
@angular/material/slide-toggle | Style changes only |
@angular/material/slider | Complete rewrite |
@angular/material/snack-bar | Style changes, API changes |
@angular/material/table | Style changes only |
@angular/material/tabs | Style changes, API changes |
@angular/material/tooltip | Style changes only |
与旧的实现相比,重构的组件具有多种优势,包括:
- 改进的无障碍
- 更好地遵守 Material Design 规范
- 由于基于通用基础设施,Material Design 规范未来版本的被采用速度更快
2. 发生了哪些变化?
新组件具有不同的内部 DOM 和 CSS 样式。 然而,大多数 TypeScript API 和新组件的组件/指令选择器都尽可能接近旧的实现。 这使得迁移应用程序并使其与新组件一起运行变得简单。
由于新的 DOM 和 CSS,您可能会发现应用程序中的某些样式需要调整,特别是当您的 CSS 覆盖任何迁移组件上的内部元素的样式时。
为了与 MDC 集成,有一些组件对其 API 进行了较大的更改。 这些组件包括:
- form-field
- chips
- slider
- list
有关所有组件更改请参阅变更完整列表。
每个新组件的旧实现现已弃用,但仍可通过“legacy”导入使用。 例如,您可以导入旧的 mat-button 实现,可以通过导入旧的按钮模块来使用。
1 | import { MatLegacyButtonModule } from "@angular/material/legacy-button"; |
3. 如何迁移
您可以通过运行 Angular Material 的自动重构工具来开始迁移。该工具以Angular Schematic 的形式实现,可将大部分代码更新为新的组件版本。虽然一些后续工作是必要的,但您可以通过遵循以下最佳实践来减少手动工作量:
通过确保您的应用程序在迁移之前遵循良好实践,您可以减少所需的手动工作量
- 尽可能避免覆盖 Angular Material 元素的内部 css 样式。如果您发现自己经常覆盖 Angular Material 元素的样式,请考虑使用专为更多自定义样式而设计的组件,例如 Angular CDK 中提供的组件。
- 在测试中使用 component harnesses 与 Angular Material 组件交互,而不是检查组件的内部元素、属性或方法。使用 component harnesses 使您的测试更容易理解并且对 Angular Material 的变化更加稳健。
3.1. 更新至 Angular Material v15
Angular Material 包含一个工作流工具(Schematic),可帮助迁移应用程序以使用新的基于 MDC 的组件。首先,请将您的应用程序升级到 Angular Material 15。
1 | ng update @angular/material@15 |
作为此更新的一部分,将运行 Schematic 以自动移动您的应用程序以使用包含旧组件实现的“legacy”导入。这提供了一条让您的应用程序在 v15 上运行的快速路径,只需最少的手动更改。
3.2. 使用迁移工具
当使用上面的命令升级到 Angular Material v15 之后, 我们可以运行迁移工具从旧的 Angular material 组件迁移到新的基于 MDC 的组件.
1 |
|
这条指令将会更新 TypeScript 文件, 样式单, 和 html 模板, 使用新的组件, 这条指令将尽可能多的自动转换, 但是后续人需要手工更新一些遗漏的地方.
3.2.1. 执行部分更新
根据应用程序的大小和复杂性,您可能希望一次迁移单个组件或一部分组件,而不是一次迁移所有组件。
您可能还想一次迁移一个模块,而不是一次性完成全部迁移。您可以在同一应用程序中同时使用旧实现和新实现,只要它们不在同一 NgModule 中即可。
迁移脚本将指引您输入要迁移的目录和组件。
3.3. 检查迁移工具遗留下 TODO 备注
某些情况下, 迁移工具不能自动更新你的部分代码, 它会在代码前加上一些 TODO 备注方便后续手段更新. 这些 TODO 备注的样式如下所示:
1 | // TODO(mdc-migration): ... |
在您的 IDE 中使用关键字”TODO(mdc-migration):”即可以找打所有这些备注.
3.4. 验证应用
运行完迁移工具并且手动处理完这些 TODO 备注后, 我们就可以着手验证我的应用程序是否依然能正常工作了.
运行自动化测试确保测试都能通过. 有些测试依赖旧组件的 Internal DOM 结构和异步时间详细信息, 这些测试可能需要修改. 如果您打算修改一些测试, 考虑使用component harnesses, 这样可以使得您的测试更加健壮.
将应用运行起来并验证新的组件是不是看起来是否有差异. 因为一些处理内部 DOM 和样式的代码, 你可能需要重新调整一些样式.
到这里迁移工作大致已经完成. 下面是从旧的 Angular Material 组件迁移到 MDC-based 组件的完整变更列表, 供您参考.
4. 完整变更列表
4.1. 库范围的更改
组件大小、颜色、间距、阴影和动画都会在各个方面略有变化。这些更改通常会更加符合 Material Design 规范和可访问性。
所有组件的 DOM 结构都已更改,以改进可访问性并更好地遵循 Material Design 规范。
应用于组件的 CSS 类使用 mat-mdc-前缀,而以前它只是一个 mat-前缀。与旧实现中的元素大致对应的元素被赋予了相同的类名(前缀除外)。例如,按钮的主机类是 mat-mdc-button 而不是 mat-button。但是,并非先前实现中的所有元素在新实现中都具有等效元素。
与 mat-typography 关联的类样式不再自动生成。你必须使用 mat.typography-hierarchy mixin 来包含它们。
4.2. 主题
mat.define-typeography-config 定义的默认排版级别已更新,以反映对 Material Design 规范的更改。
现在,所有组件都具有可主题化的(themeable)密度。默认情况下,当包含 theme mixin 时,将包含默认密度 Level(0)的样式。
1 |
|
如果您喜欢不同的默认密度级别,可以在主题配置中进行设置:
1 |
|
4.3. Autocomplete
- 长选项现在换行而不是截断。
- 选项高度不再限制在 48 像素。
- 选项列表现在有一个 8px 的顶部和底部填充。
- 选项列表现在具有打开和关闭时的动画。
4.4. Button
图标按钮的高度和宽度是 48px,而不是 40px。
状态颜色(悬停、聚焦、活动)略有不同,以提高文本对比度。
字母间距为 1.25 像素,而非正常值。
FAB 支持具有 extended 输入属性的文本。
主题 mixins 被分为三个单独的 mixins:
普通按钮(默认、凸起、stroked、平面):mat.mdc-button-theme
图标按钮:mat.mdc-Icon-button-theme
FAB:mat.mdc-fab-theme
按钮内容中的图标位于按钮文本之前。添加 iconPositionEnd 属性以将它们放置在按钮文本之后。
按钮内容中的图标继承文本字体大小。只有图标而没有文本的按钮无法正确对齐(这不适用于图标按钮)
4.5. Card
默认情况下,mat-card 不应用任何内部填充。相反,这种填充是在卡片内容区域上定义的:< mat-card-content >、< mat-card-header >和< mat-card-action >。
< mat-card-content >不再设置任何排版样式,用户可以自由地将任何对其应用有意义的排版样式添加到< mat-card-content >本身或任何子元素中(视情况而定)。例如:
1 | @use "@angular/material" as mat; |
1 | <mat-card> |
4.6. Checkbox
在新的 MDC-based Angular Material 组件中, 复选框的行为发生了一些变化. 在单击复选框时, 事件直接在原生复选框元素上触发, 而不是在填充 div 上触发. 原生复选框在单击事件中调用 preventDefault 时会有奇怪的行为,因此用户不应在单击时调用 preventDefault。
复选框触摸目标更大,现在是 40px,而不是 16px,这更容易访问。确保在布局中留出足够的空间,以便触摸目标不会与其他组件重叠。如果您不关心可访问性,您可以通过使用 density(-1) 作为复选框来匹配以前的大小。
1 | @use "@angular/material" as mat; |
由于复选框颜色变更为基于应用程序主题,复选框颜色可能会更改为白色或黑色。以前,复选框的颜色将设置为主题的背景色。对于 MDC,它是由白色还是黑色相对于原色具有最大的对比度来决定的。
对焦状态稍暗,提高对比度。
文本样式不是继承的;您需要专门针对复选框的标签来覆盖 typography 属性。
check 或者 uncheck 复选框时,波纹将保持可见,而不是动画消失。
4.7. Chips
Chips 曾经是指令,但现在它们是组件。 这意味着它们不能再应用于其他组件。
Chips 组件已分为多个变体,与更适合可访问性的交互模式相对应。 原本的 mat-chip-list 使用 role=”listbox”,但这种交互模式并不适合所有用例。 新 Chips 具有:
<mat-chip-listbox> 和 <mat-chip-option> - 这是最接近之前的交互模式。 这是唯一支持 Chips 选择状态的变体。 此模式与 Material Design 规范中指定的 filter chips 模式一致。 当您希望用户从选项列表中选择一个或多个值时,应使用此模式。
<mat-chip-grid> 和 <mat-chip-row> - 此模式应用于任何文本输入 + Chips 交互。
<mat-chip-set> 和 <mat-chip> - 此变体没有可访问模式,并假设将在应用程序级别应用一个模式。 这允许应用程序通过 Chips 视觉效果实现自定义模式。
迁移工具始终将旧版 <mat-chip-list> 更改为 <mat-chip-listbox> 以最大程度地减少前后差异。 您应该根据具体情况单独考虑更改为 <mat-chip-grid> 或 <mat-chip-set>。 有关更多根据用例选择适当组件的指南,请参阅Chips 交互模式。
4.8. Dialog
.mat-dialog-container 不再包含 24px 填充。 但是可以使用内部对话框指令负责添加正确的填充。 如果您的对话框不使用 <mat-dialog-content> 等任何指令,这一点变化将会很明显。
mat-dialog-content 使用 Material Design 规范指定的字体设置,其中包括相当宽敞的行高。 如果您的对话框是信息密集型对话框, 在这些设置下会看起来不太好,您可以避免使用 <mat-dialog-content> 并仅使用带有自定义填充的 div,或者使用可与 mat.mdc-dialog-typography mixin 一起应用的自定义排版设置。
如果在旧对话框触发了额外的更改检测,在迁移时可能需要手动修复的更改检测问题。
4.9. Form Field
“legacy”和“standard”表单字段外观设置不再存在,因为它们已从 Material Design 规范中删除。
如果未指定标签,则删除的“legacy”外观会将 placeholder 提升为浮动标签。 如果之前未提供,则所有较新的外观设置都需要显式指定 <mat-label>。 此更改解决了不交替使用标签和占位符的可访问性最佳实践。
默认情况下,MatFormField 仍然在字段下方保留一行空间用于提示或错误文本。 然而,有一个新选项@Input() subscriptSizing: ‘fixed’|’dynamic’。 当此设置设置为 fixed(默认)时,表单字段在布局中保留足够的空间来显示一行提示或错误文本。 当设置为动态时,表单字段会扩展和收缩布局所需的空间量来显示的错误/提示。
<mat-hint> 内的文本更大、更暗,以符合 W3C text 准则。
虽然以前的表单字段具有单个前缀指令 (matPrefix) 和单个后缀指令 (matSuffix),但基于 MDC 的表单字段区分与输入文本基线对齐的文本前缀/后缀和图标前缀 /后缀在表单字段中居中对齐。 使用 matTextPrefix 或 matTextSuffix 指示文本前缀/后缀,使用 matIconPrefix 或 matIconSuffix 指示图标前缀/后缀。 旧的 matSuffix 和 matPrefix API 的行为类似于图标,尽管它们现在已被弃用。
floatLabel 输入不再接受“never”。 floatLabel=”never” 仅并旧表单字段外观支持。 它用于实现行为类似于占位符的浮动标签。 如果您需要此行为,请改用 <input> 上的占位符属性。
自定义表单字段控件可能需要调整其样式,因为表单字段 周围的 DOM 和样式可能已经改变了。
4.10. Input
MatInput 必须位于 <mat-form-field> 内。 以前,如果页面在其他地方加载了表单字段样式,则可以使用不带表单字段的 <input matInput>。
基于 MDC 的 MatInput 会隐藏与 <input matInput type=”date”> 关联的原生日历选择器指示符,如果您希望此指示符在您的输入中显示,请使用以下样式:
1 | input.mat-mdc-input-element::-webkit-calendar-picker-indicator { |
4.11. List
API 已经过修改,以支持文本换行,并更好地与 Material Design 规范集成。
以前,列表项通常是使用 matLine 指令创建多个 span 元素。每个 span 生成一行,第一行成为主要行。在新的 API 中,matLine 指令被拆分为两个更精细、更有意义的指令:
- matListItemTitle
- matListItemLine
matListItemLine 之外的文本(所谓的“无范围内容”)将生成额外的行。
1 | <mat-list-item> |
该列表会自动推断文本内容的行数。例如,在上面的代码段中,列表项为两行呈现空间。使用新的 API,可以在<mat-list-item>上设置明确的行数,以手动控制换行。
1 | <mat-list-item lines="3"> |
请注意,matListItemTitle 或 matListItemLine 中的文本不会换行。根据提供的行数,只有无范围内容才会占用剩余空间。
除了行的组成方式不同之外,其他一些指令也被重命名为使用更明确的命名:
matListIcon 变更为 matListItemIcon
matListAvatar 变更为 matListItemAvatar
最后,还有一个新指令(matListItemMeta)可用于将内容放入列表项的 meta section(通常是列表项的末尾)。列表项中以前无范围内容被放入 meta section。
List 建议的迁移步骤如下:
将第一个 matLine 更改为 matListItemTitle
将所有其他 matLine 更改为 matListItemLine
将所有 matListIcon 更改为 matListItemIcon
将所有 matListAvatar 更改为 matListItemAvatar
将所有无范围内容(matLine 之外的内容)包装在 matListItemMeta 容器中。
5. Menu
无论 DOM 中的顺序如何,菜单项的图标都会出现在文本之前。
如果您有一段内容(如< img >)要用来代替< mat-icon >,请使用 ngProjectAs=“mat-icon”将其投影到图标槽中。
如果你需要你的图标出现在项目的末尾(规范不正式支持),你可以将文本和图标包装在一个 span 中,例如:
1 | <span> |
菜单项中的文本换行,而不是用省略号隐藏。
菜单项高度不再限制在 48 像素。
菜单标高从标高 8 开始,而不是从标高 4 开始。
5.1. Option / Optgroup
长选项现在换行,而不是用省略号截断。
选项高度不再限制在 48 像素。
5.2. Paginator
mat-paginator 内部的表单字段仅支持新表单字段提供的外观选项(fill 和 outline)。
5.3. Progress Bar
内部元素的可见性现在设置为 visible。设置 visibility: hidden 将不再隐藏所有内部元素。如果要隐藏内部元素,使用 opacity:0、display:none 设置样式,或者使用 ngIf 将其完全删除。
高度始终设置为 4px,并且使用高度样式不会变矮或变高。
5.4. Progress Spinner
Host element 的 display 样式不再是可能影响布局的 display: block。若要解决布局问题,请将 display:block 添加回元素。
5.5. Radio
单选按钮标签不再是宽度:100%。这有助于防止用户在单击页面上空白时意外选中单选按钮。
标签更小,离单选按钮更远,以符合“Material Design”规范。
触控目标现在更大,更容易触碰。确保在布局中留出足够的空间,以便触摸目标不会与其他组件重叠。如果你不关心可访问性,你可以通过对单选按钮使用 density-1 来匹配以前的尺寸。
1 | @use "@angular/material" as mat; |
5.6. Select
MatSelect 不再将下拉菜单中的选定选项与 trigger text 对齐。
长选项现在换行而不是截断。
选项高度不再限制在 48 像素。
选项列表现在有一个 8px 的顶部和底部填充。
选项列表动画已更改。
以前,下拉菜单的宽度可以比父 form-field 宽,但现在下拉菜单与父 form-field 的宽度相同
5.7. Slide Toggle
为了提高可访问性,基于 MDC 的版本使用 <button role=”switch”> 来表示切换,而不是 <input type=”checkbox”>。 滑动切换将不再响应原生表单验证。 考虑使用表单验证的替代方法。
触摸目标更大且更容易触及。 请务必在布局中留出足够的空间,以便触摸目标不会与其他组件重叠。 如果您不关心可访问性,您可以通过使用滑动切换的密度 -1 来匹配以前的尺寸。
1 | @use "@angular/material" as mat; |
标签更靠近滑动切换按钮
5.8. Slider
Slider 现在可以与移动设备屏幕阅读器配合使用。
滑块模板 API 已从单个<mat-slider>元素更改为包含一个或两个<input>元素(取决于滑块应为标准滑块还是范围滑块)的<mat-srider>元素。例如。
1 | <!-- Single slider --> |
< mat-slider >上的新的 discrete 特性现在控制滑块是否具有 tick marks 和 value indicator 提示。它取代了 thumbLabel。
1 | <!-- Before --> |
tickInterval 属性已被删除。要切换到新的 API,请使用 showTickMarks 创建带有刻度线的滑块,刻度线的间隔将与滑块的步长相匹配。tickInterval 属性正在考虑在将来的版本中重新添加。
1 | <!-- Before --> |
displayValue 属性已被删除。控制数值指示器文本的建议替代方案是通过 displayWith 提供的函数。
1 | <!-- Before --> |
valueText 属性已经被删除,以便直接使用 native input 的 aria valueText 或使用 displayWith 属性指定的函数。
1 | <!-- Before --> |
slider API 也发生了更改,出现了两个新组件:MatSliderThumb 和 MatSliderRangeThumb。它们提供以下属性:
- @Input() value: number
- @Output() valueChange: EventEmitter<number>
- @Output() dragEnd: EventEmitter<MatSliderDragEvent>
- @Output() dragStart: EventEmitter<MatSliderDragEvent>
- percentage: number And the following methods:
- blur
- focus
为了适应范围滑块,实现方式已从作为表单控件的< mat-slider >元素更改为包含 1-2 个< input >元素的滑块,这些 input 元素用作表单控件。值、关联的事件(输入、更改)和标签(aria 标签)现在都存在于<input>元素中。
垂直滑块和反转滑块不再受支持,因为它们不再是“材质设计”等级库的一部分。因此,反转和垂直特性已被删除。
垂直滑块和反转滑块不再受支持,因为它们不再是 Material Degsin 规范的一部分。因此,反转和垂直特性已被删除。
5.9. Snack Bar
对于简单的、基于文本的 Snack Bar 来说,没有什么显著的变化。
对于带有动作按钮的简单 Snack Bar,其为使用 MDC-based 的 mat-button,因此您的应用程序需要包含基于 MDC 按钮的 Sass 主题 mixin。
对于使用自定义结构化内容的 Snack Bar(如果您调用 MatSnackBar.openFromComponent 或 MatSnackBar.openFromTemplate),您应该使用以下新指令来 annotate 您的内容:
matSnackBarLabel 标记显示给用户的文本
matSnackBarActions 标记包含操作按钮的元素
matSnackBarAction 标记各个操作按钮
如果您没有指定这些指令中的任何一个,它将把整个自定义组件/模板视为文本。
那些打开 Snack Bar 的测试代码现在需要在尝试访问 Snack Bar 的内容之前调用 flush()。在运行迁移工具之前更新您的测试以使用component harnesses应该可以实现无缝转换。
5.10. Table
所有单元格都有 16px 的左右填充,而不仅仅是最左边和最右边的单元格有 24px 的填充。
标题单元格具有与数据行相同的颜色和文本大小,而不是具有更多的灰色和更小的文本。
默认情况下,单元格文本不再换行。可以通过对表格单元格应用 white-space: normal 来启用单元格换行。
行高是 52 像素,而不是 48 像素。
单元格的 box-sizing 是 border-box,而不是 content-box。这可能会影响自定义宽度样式。
表的最后一行不包括底部边框,因为 table 应具有底部边框。
MatTableDataSource 的 paginator 属性有一个通用接口,该接口与大多数分页器 API 匹配,但不是全部。您可能需要显式键入分页器才能访问完整的 API,例如:new MatTableDataSource<MyData,MatPaginator>();
Flex tables(< mat-table >)在单元格上显示边框,而不是在行上显示边框。
Flex tables(< mat-table >)使用 height 而不是 line-height 来设置行高。
5.11. Tabs
当 Tab 被选中时, 被选中的 Tab 标题标签文本颜色与主题颜色匹配
标题标签拉伸以填充 header 容器的宽度。但是这个行为可以被关闭, 要关闭拉升效果, 可以将<mat-tab-group>的 mat-stretch-tabs 属性设置为 false。
<mat-tab-nav-bar>需要使用 tabPanel 属性引用一个<mat-tab-nav-panel>。<mat-tab-nav-panel> 必须包裹连接到导航栏的内容。
1 | <!-- Before --> |
5.12. Tooltip
背景颜色是不透明的,而不是略微透明的。这提高了可访问性。
默认字体大小是 12px,而不是 10px。
行高是 normal ,而不是 16px。
文本溢出是省略号而不是 clip。
有一个新的最小宽度 40px。
单行工具提示的文本对齐方式居中。多行工具提示使用左对齐。
6. 相关阅读
本技术博客原创文章位于鹏叔的技术博客 - MDC-based Angular Material 组件迁移, 要获取最近更新请访问原文. 更多 Angular 相关文章请访问Angular 合集 | 鹏叔的技术博客, 更多 Material Design 相关文章请访问鹏叔的技术博客 - Material Design 专题.
更多技术博客请访问: 鹏叔的技术博客
更多 Angular Material 相关文章请站内搜索 Angular 和 Material.
7. 参考文档
Migrating to MDC-based Angular Material Components
What’s new in Angular Material and the CDK in Angular 15
Angular 15 现已上线:所有新功能、代码实践更改和弃用信息!
Guide to update your Angular application v13.0 -> v15.0 对于 medium applications
MDC-based Angular Material组件迁移