news 2026/9/12 17:02:41

Angular Material List 组件 API 全解析:从 mat-list 到 SelectionList 的完整开发指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Angular Material List 组件 API 全解析:从 mat-list 到 SelectionList 的完整开发指南

Angular Material List 组件 API 全解析:从 mat-list 到 SelectionList 的完整开发指南

【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components

本篇技术指南以 Angular Material(co/components 仓库)中@angular/material/list的 API 报告文件为核心骨架,系统讲解<mat-list><mat-nav-list><mat-action-list><mat-selection-list>四大列表变体的组件与指令 API、源码实现原理、无障碍实践以及官方测试 Harness 的完整用法。读完本文,你将掌握列表项内容分区指令(Title/Line/Meta)、选择列表的ControlValueAccessor双向绑定机制、单选/多选切换与hideSingleSelectionIndicator全局配置,并能用 Component Harness 编写可跨测试框架复用的列表测试。

一、文档定位:什么是 API Golden 文件

仓库中的 goldens/material/list/index.api.md 是由 API Extractor,记录@angular/material/list/testing的 Harness 测试 API。

真正的使用文档位于 src/material/list/list.md,实现源码位于 src/material/list 目录。下面我们把三者结合起来,逐层剖析。

二、列表家族总览:四种容器组件

API 报告中清晰给出了四个公开容器组件,它们都继承自内部基类MatListBase(见 src/material/list/list-base.ts):

组件选择器用途默认 role
MatListmat-list基础列表,纯展示,无行为无(装饰性)
MatNavListmat-nav-list导航列表,每个项是锚点navigation
MatActionListmat-action-list操作列表,每个项是按钮group
MatSelectionListmat-selection-list选择列表,项为可选中选项listbox

从源码看,四种容器的差异非常精简:

  • list.ts 中的MatList模板仅有<ng-content></ng-content>MatListBase_isNonInteractive = true,即默认纯装饰、无任何交互。
  • nav-list.ts 与 action-list.ts 都将_isNonInteractive覆盖为false,让列表项进入"交互模式"——源码注释说明了原因:MDC 规范下交互列表的项只通过键盘可达,而导航/操作列表希望每个项都能用 Tab 键直接聚焦,因此没有继承交互基类,而是让所有项均可通过 Tab 到达。

2.1 基础列表与列表项

最简单的用法是纯文本单行列表:

<mat-list> <mat-list-item>Pepper</mat-list-item> <mat-list-item>Salt</mat-list-item> <mat-list-item>Paprika</mat-list-item> </mat-list>

MatListItem的选择器同时支持元素形式和属性形式:mat-list-item, a[mat-list-item], button[mat-list-item](见 list.ts),因此锚点与按钮可以直接复用列表项样式。

2.2 导航列表MatNavList

导航列表用于"每一项都是跳转到其他 URL 的锚点"的场景。简单导航列表可直接在<a>上使用mat-list-item属性:

<mat-nav-list> @for (link of list; track link) { <a mat-list-item href="..." [activated]="link.isActive">{{ link }}</a> } </mat-nav-list>

activatedMatListItem的输入属性,用于标记当前激活页(见 list.ts)。它经由coerceBooleanProperty做布尔强制转换,并驱动aria-current属性:当宿主元素是<a>activated为真时返回'page',否则返回null(见 list.ts),同时通过 host 绑定添加mdc-list-item--activated样式类。

复杂导航列表(如每个条目有多个目标)则把锚点包进<mat-list-item>,再用内容分区指令组织:

<mat-nav-list> @for (link of links; track link) { <mat-list-item [activated]="link.isActive"> <a matListItemTitle href="...">{{ link }}</a> <button matIconButton (click)="showInfo(link)" matListItemMeta> <mat-icon>info</mat-icon> </button> </mat-list-item> } </mat-nav-list>

2.3 操作列表MatActionList

每个条目执行某种"动作"的列表使用<mat-action-list>,条目是<button>

<mat-action-list> <button mat-list-item (click)="save()">Save</button> <button mat-list-item (click)="undo()">Undo</button> </mat-action-list>

MatListItemBase构造器(list-base.ts)会自动为没有显式type属性的宿主<button>补上type="button",避免表单提交副作用。

三、列表项内容分区指令(核心 API)

API 报告与 list-item-sections.ts 共同定义了五个内容分区指令,是构建多行列表的关键:

指令说明对应 CSS 类
matListItemTitle列表项标题,多行列表必须,全文不换行,每项只能一个mdc-list-item__primary-text
matListItemLine列表项内的一行文本,最多两个mdc-list-item__secondary-text
matListItemIcon通常置于列表项开头的图标mat-mdc-list-item-icon
matListItemAvatar通常置于列表项开头的头像图片mat-mdc-list-item-avatar
matListItemMeta在列表项末尾的 meta 区插入内容(图标、按钮等)mdc-list-item__end

其中MatListItemIconMatListItemAvatar继承自_MatListItemGraphicBase(见 list-item-sections.ts),它根据列表项中复选框/单选钮的位置自动应用mdc-list-item__startmdc-list-item__end类:在普通列表项中图形默认对齐到开头;在MatListOption中,仅当复选框/单选钮位于末尾(togglePosition === 'after')时图形才对齐到开头。

3.1 多行列表写法

两行列表(标题 + 一行描述):

<mat-list> @for (message of messages; track message) { <mat-list-item> <h3 matListItemTitle>{{message.from}}</h3> <p matListItemLine> <span>{{message.subject}}</span> <span class="demo-2"> -- {{message.content}}</span> </p> </mat-list-item> } </mat-list>

三行列表(标题 + 两行描述):

<mat-list> @for (message of messages; track message) { <mat-list-item> <h3 matListItemTitle>{{message.from}}</h3> <p matListItemLine>{{message.subject}}</p> <p matListItemLine class="demo-2">{{message.content}}</p> </mat-list-item> } </mat-list>

注意:标题标签类型应按 DOM 层级语义自由选择(不必拘泥于示例中的<h3>)。

3.2 行数推断与lines输入

列表项的行数支持自动推断与显式声明两种方式。list-base.ts 的_inferLinesFromContent标题数 + 行数 + (有无未分区文本 ? 1 : 0)推断;list-base.ts 的lines输入则通过coerceNumberProperty显式指定行数,可激活文本换行并预留更多空间。按 Material Design 规范,列表项最多支持三行(list-base.ts)。

在开发模式下,list-base.ts 的sanityCheckListItemContent会给出四条一致性警告:一个列表项不能有多个标题;有行文本必须有标题;无标题时不能声明超过一行的换行内容;最多三行。这些检查位于顶层函数中,生产构建可被 Terser 死代码消除。

3.3 图标、头像与 Meta 区

图标列表:使用matListItemIcon

<mat-list> @for (message of messages; track message) { <mat-list-item> <mat-icon matListItemIcon>folder</mat-icon> <h3 matListItemTitle>{{message.from}}</h3> <p matListItemLine> <span>{{message.subject}}</span> <span class="demo-2"> -- {{message.content}}</span> </p> </mat-list-item> } </mat-list>

Meta 区(末尾放置图标或其他内容):使用matListItemMeta

<mat-list> @for (message of messages; track message) { <mat-list-item> <div matListItemMeta> <mat-icon>folder</mat-icon> </div> <h3 matListItemTitle>{{message.from}}</h3> <p matListItemLine> <span>{{message.subject}}</span> <span class="demo-2"> -- {{message.content}}</span> </p> </mat-list-item> } </mat-list>

头像列表:<img matListItemAvatar src="..." alt="...">即可在开头显示头像图片。当既有前导图形又有尾部 meta 时,宿主元素会获得mat-mdc-list-item-both-leading-and-trailing工具类(list.ts),便于样式统一处理。

3.4 分组小标题与分隔线

API 报告中的MatListSubheaderCssMatStyler对应[mat-subheader], [matSubheader]选择器,用于给列表分组加小标题;MatDividermat-divider)提供verticalinset两个布尔输入。组合示例:

<mat-list> <h3 matSubheader>Folders</h3> @for (folder of folders; track folder) { <mat-list-item> <mat-icon matListIcon>folder</mat-icon> <h4 matListItemTitle>{{folder.name}}</h4> <p matListItemLine class="demo-2"> {{folder.updated}} </p> </mat-list-item> } <mat-divider></mat-divider> <h3 matSubheader>Notes</h3> @for (note of notes; track note) { <mat-list-item> <mat-icon matListIcon>note</mat-icon> <h4 matListItemTitle>{{note.name}}</h4> <p matListItemLine class="demo-2"> {{note.updated}} </p> </mat-list-item> } </mat-list>

四、选择列表MatSelectionListMatListOption

选择列表是最复杂的变体,API 报告围绕它列出了最多的公开符号:MatSelectionListMatListOptionMatSelectionListChangeMatListOptionTogglePositionSelectionList接口、SELECTION_LIST令牌、MAT_SELECTION_LIST_VALUE_ACCESSOR

4.1 基本用法与事件

<mat-selection-list>提供一个选择值的界面,每个<mat-list-option>是一个选项:

<mat-selection-list [(ngModel)]="selectedOptions"> <mat-list-option value="1" [selected]="true">Option 1</mat-list-option> <mat-list-option value="2">Option 2</mat-list-option> </mat-selection-list>

选项变化通过selectionChange事件发出,载荷为MatSelectionListChange,包含source(源MatSelectionList)与options(发生变化的MatListOption[])两个字段(selection-list.ts)。

重要约束:选择列表的选项内部不应再嵌套任何交互控件(按钮、锚点等),因为整个列表是一个复合组件,其键盘与焦点行为由列表统一管理。

4.2 关键输入属性

MatSelectionList的输入属性(均可从 API 报告与 selection-list.ts 验证):

属性类型默认值说明
multiplebooleantrue是否允许多选;默认多选(显示复选框),设为false切换为单选(显示单选钮)。初始化后不可再修改,否则抛错(selection-list.ts)
colorThemePalette'accent'复选/单选钮的主题色。仅 M2 主题生效,M3 无效果(selection-list.ts)
compareWith(o1, o2) => boolean===比较判断选项值与选中值是否相等,决定哪些选项显示为选中(selection-list.ts)
hideSingleSelectionIndicatorbooleanfalse单选模式下是否隐藏指示器。可从MAT_LIST_CONFIG全局配置默认值(selection-list.ts)
disabledbooleanfalse禁用整个列表;禁用时所有选项移出 Tab 顺序(tabindex="-1")并设置aria-disabled

MatListOption的输入属性:

属性类型默认值说明
valueany选项的值;ngModel/formControl读到的就是选中项的值数组
selectedbooleanfalse选中状态,支持双向绑定[(selected)],配合selectedChange事件
togglePosition'before' \| 'after'MatListOptionTogglePosition'after'复选框/单选钮出现在文本之前还是之后
colorThemePalette继承列表的color未显式设置时回退到所属列表的颜色(list-option.ts)

MatListOption还提供toggle()focus()getLabel()等公开方法;getLabel()用于列表的 typeahead 打字过滤——优先取标题元素的文本,无标题时回退到未分区文本(list-option.ts)。

4.3 ControlValueAccessor 与表单集成

MatSelectionList实现了ControlValueAccessor(selection-list.ts),通过MAT_SELECTION_LIST_VALUE_ACCESSOR(内部常量NG_VALUE_ACCESSOR提供器)接入 Angular 表单体系,因此可无缝用于ngModelformControlName与响应式表单:

  • writeValue(values: string[]):把模型值写回视图,通过compareWith匹配选项并设置选中态(selection-list.ts)。
  • _reportValueChange():收集选中选项的值数组(_getSelectedOptionValues)并回调_onChange,实现视图到模型的同步(selection-list.ts)。
  • setDisabledState(isDisabled):同步表单禁用状态到组件。
  • registerOnChange/registerOnTouched:注册模型更新与失焦回调。

公开的selectAll()/deselectAll()返回发生变化的选项数组;selectedOptionsSelectionModel<MatListOption>,可直接编程操作选中集合。

4.4 键盘交互与焦点管理

MatSelectionList采用 WAI-ARIA 的 listbox 交互模式,通过FocusKeyManager实现漫游 Tabindex(roving tabindex)管理(selection-list.ts):

  • ArrowUp/ArrowDown在选项间移动焦点;
  • Home/End跳到首/末选项(withHomeAndEnd);
  • 连续输入字符触发 typeahead 过滤(withTypeAhead);
  • 焦点到达边界时循环(withWrap);
  • Enter/Space切换当前活动选项的选中状态(_toggleOnInteraction,跳过禁用项);
  • 多选模式下Ctrl/Cmd + A全选/取消全选(selection-list.ts)。

值得注意的细节:skipPredicate(() => false)表示禁用选项也保留在 Tab 顺序中——源码注释引用了 WAI-ARIA APG 键盘接口实践,明确指出 listbox 中的禁用选项应保持可聚焦(selection-list.ts)。

MatListOption的选中状态与指示器位置联动:多选时在指定位置渲染复选框(_hasCheckboxAt),单选且未隐藏指示器时渲染单选钮(_hasRadioAt),并据此应用mdc-list-item--with-leading-checkbox/radio等 MDC 类(list-option.ts)。

五、全局默认配置:MAT_LIST_CONFIG

API 报告中的MatListConfig接口只有一个可选字段hideSingleSelectionIndicator,配套的MAT_LIST_CONFIG注入令牌定义在 tokens.ts。它的作用是提供列表模块的全局默认选项:

providers: [ {provide: MAT_LIST_CONFIG, useValue: {hideSingleSelectionIndicator: true}}, ]

在 list-base.ts 中,MatListBase通过inject(MAT_LIST_CONFIG, {optional: true})注入该配置;MatSelectionList在初始化hideSingleSelectionIndicator时以_defaultOptions?.hideSingleSelectionIndicator ?? false作为默认值(selection-list.ts),实现"全局默认 + 实例覆盖"的两级配置。

另外,API 报告还公开了三个 DI 令牌用于解耦类引用、避免元数据滞留:MAT_LIST(list.ts)、MAT_NAV_LIST(nav-list.ts)、SELECTION_LIST(list-option.ts),后者还用于避免MatListOptionMatSelectionList之间的循环依赖。

六、模块组织:MatListModule

API 报告中的MatListModuleNgModule 声明与导出揭示了依赖关系:模块内部导入了ObserversModule(内容变更观察,用于行数自动更新)、MatRippleModule(波纹反馈)与MatPseudoCheckboxModule(伪复选框),对外导出BidiModule、四类列表、MatDividerModule及所有内容分区指令(index.api.md)。

模块的导入方式:

import {MatListModule} from '@angular/material/list'; @NgModule({ imports: [MatListModule], }) export class MyModule {}

七、无障碍实践

官方文档 list.md 对不同列表变体的无障碍要求做了明确划分:

  • 导航列表:根元素自动设置role="navigation",必须通过aria-labelaria-labelledby提供可访问标签。为获得最佳屏幕阅读器体验,建议用<ul>+<li>包裹锚点:
<mat-nav-list aria-label="Select a folder"> <ul> @for (link of list; track link) { <li> <a mat-list-item href="..." [activated]="link.isActive">{{ link }}</a> </li> } </ul> </mat-nav-list>
  • 操作列表:给<mat-action-list>添加role="list"aria-label,并用<li>包裹每个按钮:
<mat-action-list role="list" aria-label="Post actions"> <li> <button mat-list-item (click)="save()">Save</button> </li> <li> <button mat-list-item (click)="undo()">Undo</button> </li> </mat-action-list>
  • 选择列表:使用role="listbox"交互模式,键盘输入与焦点管理全部由组件处理;同样必须提供aria-labelaria-labelledby描述选择内容。文档特别提醒:hideSingleSelectionIndicator会降低可访问性——用户将更难(甚至无法)通过视觉识别选中项,因此默认保持显示单选指示器。

  • 自定义场景:默认的mat-list是纯装饰性的,不设置任何 role、ARIA 属性或键盘快捷键,等同于页面上一组<div>。若用于展示非交互内容列表,应手动为列表添加role="list"、为每个列表项添加role="listitem"

八、测试 Harness API:@angular/material/list/testing

goldens/material/list/testing/index.api.md 完整记录了官方测试 Harness。它构建在@angular/cdk/testing之上(ComponentHarnessHarnessPredicateContentContainerComponentHarness),因此同一套测试代码可运行于 Karma(真实浏览器)与 Protractor 等不同测试环境。

8.1 Harness 一览

Harness 类对应组件主要方法
MatListHarnessmat-list通过with()过滤,getItems()
MatActionListHarnessmat-action-list获取MatActionListItemHarness
MatNavListHarnessmat-nav-list获取MatNavListItemHarness
MatSelectionListHarnessmat-selection-listselectItems()deselectItems()isDisabled()
MatListItemHarnessmat-list-item文本断言、blur/focus/isFocused
MatListOptionHarnessmat-list-optionselect/deselect/toggleisSelectedgetCheckboxPosition/getRadioPosition
MatSubheaderHarnessmat-subheadergetText()

8.2 过滤器(Harness Filters)

列表项过滤器BaseListItemHarnessFilters提供了丰富的文本匹配维度:

interface BaseListItemHarnessFilters extends BaseHarnessFilters { fullText?: string | RegExp; // 完整文本 secondaryText?: string | RegExp | null; tertiaryText?: string | RegExp | null; title?: string | RegExp; text?: string | RegExp; // 已废弃 }

ListOptionHarnessFilters额外支持selected?: booleanNavListItemHarnessFilters额外支持activated?: booleanhref?: string | RegExp | nullSubheaderHarnessFilters支持text?: string | RegExp

8.3 枚举

  • MatListItemSection.CONTENT = ".mdc-list-item__content":列表项内容区块的 CSS 选择器,可用于定位文本区域。
  • MatListItemType:单行(ONE_LINE_ITEM = 0)、两行(TWO_LINE_ITEM = 1)、三行(THREE_LINE_ITEM = 2)三种行数类型。

8.4 测试示例

import {MatSelectionListHarness} from '@angular/material/list/testing'; const list = await loader.getHarness(MatSelectionListHarness); const options = await list.getItems({selected: true}); expect(options.length).toBe(1); // 通过文本选中某个选项 await list.selectItems({title: /Pepper/});

MatListHarnessBase泛型设计(如MatSelectionListHarness extends MatListHarnessBase<typeof MatListOptionHarness, MatListOptionHarness, ListOptionHarnessFilters>)使得四种列表 Harness 共享同一套"取列表、取选项、过滤"的基础逻辑,只在具体选项类型上分叉。

九、总结

@angular/material/list通过"一个基类 + 四种容器 + 五类内容分区指令"的组合,覆盖了展示、导航、操作、选择四大列表场景。其中选择列表是 API 最密集的组件:ControlValueAccessor表单集成、SelectionModel状态管理、listbox 键盘交互与 roving tabindex 均由组件内置。API golden 文件与源码 src/material/list、官方文档 list.md 三者相互印证,是开发者查阅公共契约、理解实现细节与编写测试的权威依据。更多进阶内容(如 M3 主题下的颜色定制)可继续研读仓库中的主题样式文件 src/material/list/_list-theme.scss 与 src/material/list/_m3-list.scss。

【免费下载链接】componentsComponent infrastructure and Material Design components for Angular项目地址: https://gitcode.com/GitHub_Trending/co/components

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 17:02:14

GA-VMD参数自适应寻优:旋转机械故障诊断中的振动信号处理实践

简介&#xff1a;遗传算法优化VMD&#xff08;GA-VMD&#xff09;技术结合遗传算法与变分模态分解&#xff0c;面向非线性、非平稳信号分析需求&#xff0c;适用于电力系统故障诊断、机械健康监测、声音识别等场景。资源包共27个文件&#xff0c;以15个Matlab脚本为核心&#x…

作者头像 李华
网站建设 2026/9/12 17:01:40

TEC半导体制冷片在医用冷敷仪中的精准控温原理与工程实现

1. 为什么冷敷仪不能只靠冰袋&#xff1f;TEC半导体制冷片的不可替代性 市面上卖的手持冷敷仪&#xff0c;十有八九是“伪冷敷”——要么是内置凝胶冰袋&#xff0c;靠提前冷冻后缓慢释冷&#xff1b;要么是压缩机制冷&#xff0c;体积大、噪音响、功耗高&#xff0c;根本没法做…

作者头像 李华