
本文介绍如何在 Angular Material 中正确构建支持键盘导航、可选中且结构清晰的嵌套列表,避开 mat-selection-list 嵌套限制,改用 mat-list + 手动管理 mat-checkbox 实现语义化、可访问性良好的层级选择控件。
本文介绍如何在 angular material 中正确构建支持键盘导航、可选中且结构清晰的嵌套列表,避开 `mat-selection-list` 嵌套限制,改用 `mat-list` + 手动管理 `mat-checkbox` 实现语义化、可访问性良好的层级选择控件。
Angular Material 的
✅ 正确方案:使用
✅ 推荐实现结构(含完整示例)
<mat-list><ng-container item of items trackby: trackbyindex let outerindex='$index"'><!-- 顶层项 --><mat-list-item><mat-checkbox class="example-margin" outerindex>
{{ item.name }}
</mat-checkbox></mat-list-item><!-- 子项(缩进增强视觉层级) --><mat-list style="margin-left: 32px; padding: 0;"><div subitem of item.subitems trackby: trackbyindex let innerindex='$index"'>
<mat-list-item><mat-checkbox class="example-margin" outerindex innerindex item>
{{ subItem.name }}
</mat-checkbox></mat-list-item>
</div>
</mat-list></ng-container></mat-list>
对应 TypeScript 控制器(推荐使用 trackBy 提升性能):
import { Component } from '@angular/core';
@Component({
selector: 'list-overview-example',
templateUrl: 'list-overview-example.html',
})
export class ListOverviewExample {
items = [
{
name: 'Electronics',
checked: false,
subItems: [
{ name: 'Smartphones', checked: false },
{ name: 'Laptops', checked: false },
{ name: 'Headphones', checked: false }
]
},
{
name: 'Clothing',
checked: false,
subItems: [
{ name: 'T-Shirts', checked: false },
{ name: 'Jeans', checked: false }
]
}
];
// 避免重复创建对象引用,提升渲染性能
trackByIndex(index: number) {
return index;
}
onParentChange(parent: any) {
// 可选:联动子项(全选/取消全选)
parent.subItems.forEach((child: any) => child.checked = parent.checked);
}
onChildChange(child: any, parent: any) {
// 可选:更新父项状态(当所有子项选中时父项自动选中)
const allSelected = parent.subItems.every((s: any) => s.checked);
parent.checked = allSelected;
}
}
⚠️ 关键注意事项
- 禁止嵌套 mat-selection-list:Angular Material 官方明确不支持此用法,会导致 ARIA 层级混乱、焦点丢失及屏幕阅读器不可读。
- 必须设置 trackBy:尤其在动态数据场景下,避免因对象引用变化触发不必要的 DOM 重绘。
- 合理缩进与间距:使用 margin-left 或 CSS padding-inline-start 明确表达层级关系,提升可读性(注意:避免过度依赖内联样式,建议提取为 SCSS 类)。
-
无障碍增强建议:
- 为每个 mat-checkbox 添加唯一 id 和语义化 name;
- 若需父子联动逻辑,务必在 change 事件中同步更新状态,并确保变更可被 ngModel 或响应式表单捕获;
- 考虑添加 aria-label 或 aria-labelledby 以明确父子关系(例如:Electronics +
...)。
✅ 总结
当你需要可键盘导航、可选中、具备清晰层级的嵌套列表时,请放弃尝试嵌套 mat-selection-list,转而采用 mat-list + mat-checkbox 的组合模式。它不仅完全兼容 Angular Material 的可访问性规范(WCAG 2.1),还能灵活控制父子联动逻辑、样式定制与状态管理,是生产环境中的稳定、标准解法。











