MDC-based Angular Material组件迁移

1. 前言

在 Angular Material v15 中,许多组件已基于官方的 Web Material Design Components (MDC) 进行了重构。 以下导入的组件已被重构:

Import pathSummary of changes
@angular/material/autocompleteStyle changes only
@angular/material/buttonStyle changes, API changes
@angular/material/cardStyle changes only
@angular/material/checkboxStyle changes, changes to event behavior
@angular/material/chipsComplete rewrite
@angular/material/coreStyle changes only
@angular/material/dialogStyle changes, changes to change detection behavior
@angular/material/form-fieldStyle changes, some appearances removed, API changes
@angular/material/inputStyle changes only
@angular/material/listStyle changes, API changes
@angular/material/menuStyle changes, API changes
@angular/material/paginatorStyle changes only
@angular/material/progress-barStyle changes only
@angular/material/progress-spinnerStyle changes only
@angular/material/radioStyle changes only
@angular/material/selectStyle changes only
@angular/material/slide-toggleStyle changes only
@angular/material/sliderComplete rewrite
@angular/material/snack-barStyle changes, API changes
@angular/material/tableStyle changes only
@angular/material/tabsStyle changes, API changes
@angular/material/tooltipStyle 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
2
3

ng generate @angular/material:mdc-migration

这条指令将会更新 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
2
3
4
5
6
7
8
9
10

@use '@angular/material' as mat;

$theme: mat.define-light-theme((
color: ...
));

// Adds density level 0 styles
@include mat.all-component-themes($theme);

如果您喜欢不同的默认密度级别,可以在主题配置中进行设置:

1
2
3
4
5
6

$theme: mat.define-light-theme((
color: ...,
density: -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
2
@use "@angular/material" as mat;
@include mat.typography-hierarchy();
1
2
3
<mat-card>
<mat-card-content class="mat-body-1">...</mat-card-content>
</mat-card>

4.6. Checkbox

在新的 MDC-based Angular Material 组件中, 复选框的行为发生了一些变化. 在单击复选框时, 事件直接在原生复选框元素上触发, 而不是在填充 div 上触发. 原生复选框在单击事件中调用 preventDefault 时会有奇怪的行为,因此用户不应在单击时调用 preventDefault。

复选框触摸目标更大,现在是 40px,而不是 16px,这更容易访问。确保在布局中留出足够的空间,以便触摸目标不会与其他组件重叠。如果您不关心可访问性,您可以通过使用 density(-1) 作为复选框来匹配以前的大小。

1
2
@use "@angular/material" as mat;
@include mat.checkbox-density(-1);

由于复选框颜色变更为基于应用程序主题,复选框颜色可能会更改为白色或黑色。以前,复选框的颜色将设置为主题的背景色。对于 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
2
3
input.mat-mdc-input-element::-webkit-calendar-picker-indicator {
display: block;
}

4.11. List

API 已经过修改,以支持文本换行,并更好地与 Material Design 规范集成。
以前,列表项通常是使用 matLine 指令创建多个 span 元素。每个 span 生成一行,第一行成为主要行。在新的 API 中,matLine 指令被拆分为两个更精细、更有意义的指令:

  • matListItemTitle
  • matListItemLine

matListItemLine 之外的文本(所谓的“无范围内容”)将生成额外的行。

1
2
3
4
<mat-list-item>
<span matListItemTitle>Title</span>
Second line
</mat-list-item>

该列表会自动推断文本内容的行数。例如,在上面的代码段中,列表项为两行呈现空间。使用新的 API,可以在<mat-list-item>上设置明确的行数,以手动控制换行。

1
2
3
4
5
<mat-list-item lines="3">
<span matListItemTitle>Title</span>
This text will wrap into the third line. Space for three lines is acquired by
the list item.
</mat-list-item>

请注意,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
2
3
4
<span>
<span>Text</span>
<mat-icon>end_icon</mat-icon>
</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
2
@use "@angular/material" as mat;
@include mat.radio-density(-1);

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
2
@use "@angular/material" as mat;
@include mat.slide-toggle-density(-1);

标签更靠近滑动切换按钮

5.8. Slider

Slider 现在可以与移动设备屏幕阅读器配合使用。

滑块模板 API 已从单个<mat-slider>元素更改为包含一个或两个<input>元素(取决于滑块应为标准滑块还是范围滑块)的<mat-srider>元素。例如。

1
2
3
4
5
6
7
8
9
10
<!-- Single slider -->
<mat-slider>
<input matSliderThumb />
</mat-slider>

<!-- Range slider -->
<mat-slider>
<input matSliderStartThumb />
<input matSliderEndThumb />
</mat-slider>

< mat-slider >上的新的 discrete 特性现在控制滑块是否具有 tick marks 和 value indicator 提示。它取代了 thumbLabel。

1
2
3
4
5
6
7
<!-- Before -->
<mat-slider thumbLabel></mat-slider>

<!-- After -->
<mat-slider discrete>
<input matSliderThumb />
</mat-slider>

tickInterval 属性已被删除。要切换到新的 API,请使用 showTickMarks 创建带有刻度线的滑块,刻度线的间隔将与滑块的步长相匹配。tickInterval 属性正在考虑在将来的版本中重新添加。

1
2
3
4
5
6
7
<!-- Before -->
<mat-slider tickInterval="5" step="5"></mat-slider>

<!-- After -->
<mat-slider step="5" showTickMarks>
<input matSliderThumb />
</mat-slider>

displayValue 属性已被删除。控制数值指示器文本的建议替代方案是通过 displayWith 提供的函数。

1
2
3
4
5
6
7
<!-- Before -->
<mat-slider [displayValue]="myDisplayValue"></mat-slider>

<!-- After -->
<mat-slider [displayWith]="myDisplayWithFn">
<input matSliderThumb />
</mat-slider>

valueText 属性已经被删除,以便直接使用 native input 的 aria valueText 或使用 displayWith 属性指定的函数。

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Before -->
<mat-slider [valueText]="myValueText"></mat-slider>

<!-- After (Option 1) -->
<mat-slider>
<input [attr.aria-valuetext]="myValueText" matSliderThumb />
</mat-slider>

<!-- After (Option 2) -->
<mat-slider [displayWith]="myDisplayWithFn">
<input matSliderThumb />
</mat-slider>

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
2
3
4
5
6
<!-- Before -->
<mat-tab-nav-bar>...</mat-tab-nav-bar>

<!-- After -->
<mat-tab-nav-bar [tabPanel]="tabPanel">...</mat-tab-nav-bar>
<mat-tab-nav-panel #tabPanel>...</mat-tab-nav-panel>

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 Schematics 介绍

Angular 15 现已上线:所有新功能、代码实践更改和弃用信息!

Guide to update your Angular application v13.0 -> v15.0 对于 medium applications