news 2026/9/12 18:27:27

Angular Material Expansion 完全指南:mat-expansion-panel 与 mat-accordion 从用法到源码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Angular Material Expansion 完全指南:mat-expansion-panel 与 mat-accordion 从用法到源码解析

Angular Material Expansion 完全指南:mat-expansion-panel 与 mat-accordion 从用法到源码解析

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

mat-expansion-panel是 Angular Material 提供的可展开「详情—摘要」视图组件,用于在有限页面空间内展示可折叠的内容区块;mat-accordion则用于将多个面板组织成手风琴式布局。本文以本仓库官方文档 expansion.md 为主线,结合真实源码与示例,系统讲解面板结构、标题栏定制、操作栏、禁用态、手风琴模式、懒渲染与无障碍实现,帮助你从 API 用法一路深入到组件内部原理。

一、组件总览:面板、标题与手风琴

在 Angular Material 的 Expansion 模块中,主要包含三个可组合的构件:

构件选择器职责
展开面板<mat-expansion-panel>承载可展开/折叠的内容区域,等价于原生<details>的语义
面板标题<mat-expansion-panel-header>显示摘要信息,同时是展开/折叠的交互控制区
手风琴容器<mat-accordion>把多个面板组织成手风琴,管理同一时刻可展开的面板数量

三者对外统一由MatExpansionModule导出,模块定义位于 expansion-module.ts,公共 API 清单见 public-api.ts。使用前在应用中引入该模块(或采用独立组件导入方式)即可。

从组件层级看,MatExpansionPanel继承自 CDK 的CdkAccordionItem(参见 expansion-panel.ts),因此天然获得expanded状态、opened/closed事件以及toggle()/open()/close()编程接口;MatAccordion则继承自CdkAccordion(参见 accordion.ts),负责面板之间的互斥与批量操作。

二、面板内容与 Header 定制

2.1 Header:标题 + 描述

<mat-expansion-panel-header>显示面板内容的摘要,并充当展开/折叠的控制按钮。它内部可包含<mat-panel-title><mat-panel-description>两个指令(分别映射到源码中的MatExpansionPanelTitleMatExpansionPanelDescription,见 expansion-panel-header.ts),用于按 Material Design 规范对齐标题栏内容:

<mat-expansion-panel-header> <mat-panel-title>This is the expansion title</mat-panel-title> <mat-panel-description>This is a summary of the content</mat-panel-description> </mat-expansion-panel-header>

上述用法来自官方示例 expansion-overview-example.html。从模板源码看,标题栏由三部分组成:mat-panel-titlemat-panel-description以及一个兜底的ng-content插槽,结构见 expansion-panel-header.html。也就是说,除了标准标题与描述,你还可以直接放入任意自定义内容。

2.2 展开指示图标与 hideToggle

默认情况下,Header 末尾会渲染一个指示展开状态的切换图标(V 形箭头)。该图标由模板中的.mat-expansion-indicator配合内联 SVG 实现(见 expansion-panel-header.html),并通过_showToggle()方法控制是否渲染——该方法在hideToggle或面板disabled时返回false(见 expansion-panel-header.ts)。

如果不需要图标,可通过hideToggle属性隐藏:

<mat-expansion-panel hideToggle> <mat-expansion-panel-header> <mat-panel-title>This is the expansion title</mat-panel-title> <mat-panel-description>This is a summary of the content</mat-panel-description> </mat-expansion-panel-header> <p>This is the primary content of the panel.</p> </mat-expansion-panel>

该片段对应示例中的hide-toggle区域(见 expansion-overview-example.html)。hideToggle既可以写在单个面板上,也可以统一写在mat-accordion上作用于其下所有面板——源码中面板的hideTogglegetter 在自身未设置时会回退读取this.accordion.hideToggle(见 expansion-panel.ts)。

2.3 指示图标位置:togglePosition

除了隐藏图标,还可以通过togglePosition将图标放到标题栏的前面before)或后面after,默认值),取值为MatAccordionTogglePosition类型(见 accordion-base.ts)。模板中通过_getTogglePosition()动态绑定after/before两个 class(见 expansion-panel-header.ts)。

2.4 自定义 Header 高度

Header 支持expandedHeightcollapsedHeight两个输入,分别指定展开态与折叠态的高度;未设置时返回null,交由样式表默认高度处理(见 expansion-panel-header.ts)。这两个值同样可以像hideToggle一样通过MAT_EXPANSION_PANEL_DEFAULT_OPTIONS注入令牌全局配置(见 expansion-panel.ts)。

三、Action Bar:展开后显示的底部操作区

面板底部可以放置一组「操作行」(action bar),且仅在面板展开时可见。用法如下,出自示例 expansion-steps-example.html:

<mat-expansion-panel [expanded]="step() === 0" (opened)="setStep(0)" hideToggle> <mat-expansion-panel-header> <mat-panel-title>Personal data</mat-panel-title> <mat-panel-description>Type your name and age</mat-panel-description> </mat-expansion-panel-header> <mat-form-field> <mat-label>First name</mat-label> <input matInput /> </mat-form-field> <mat-action-row> <button matButton (click)="nextStep()">Next</button> </mat-action-row> </mat-expansion-panel>

<mat-action-row>对应源码中的MatExpansionPanelActionRow指令,仅挂载mat-action-rowclass(见 expansion-panel.ts)。在面板模板中它被ng-content select="mat-action-row"匹配并放置在正文之后(见 expansion-panel.html),配合「上一步/下一步」按钮,非常适合做分步表单、向导式流程(expansion-steps示例即演示了这一场景)。

四、禁用面板:disabled

通过disabled属性可以禁用单个面板:

<mat-expansion-panel disabled> <mat-expansion-panel-header> <mat-panel-title>Destination</mat-panel-title> <mat-panel-description>Type the country name</mat-panel-description> </mat-expansion-panel-header> ... </mat-expansion-panel>

该片段来自示例中的disabled区域(见 expansion-expand-collapse-all-example.html)。被禁用的面板用户无法手动切换,但仍可通过编程方式操控——因为toggle()等方法的执行路径(MatExpansionPanelHeader._toggle())在disabled时直接返回(见 expansion-panel-header.ts),而面板本身的open()/close()/toggle()方法并不受此限制(见 expansion-panel.ts)。此外,disabled会同步反映为标题栏的aria-disabled,并将tabindex置为-1使其移出键盘 Tab 焦点序列(见 expansion-panel-header.ts)。

五、Accordion 手风琴模式

多个<mat-expansion-panel>放进同一个<mat-accordion>即组成手风琴:

<mat-accordion class="example-headers-align" multi> <mat-expansion-panel> ... </mat-expansion-panel> <mat-expansion-panel> ... </mat-expansion-panel> <mat-expansion-panel> ... </mat-expansion-panel> </mat-accordion>

5.1 multi:独立展开状态

multi="true"允许各面板独立展开/折叠,互不影响;multi="false"(默认)则保证同一时刻最多只有一个面板处于展开状态,展开新面板时旧面板自动收起。源码中MatAccordion通过CdkAccordion的互斥逻辑实现这一点,示例见 expansion-expand-collapse-all-example.html 的multi区域。

5.2 displayMode:default 与 flat

mat-accordion支持两种显示模式(见 accordion.ts):

  • default(默认):展开的面板四周带有类似「沟槽」的间距,使其与其余面板产生不同的高度层级(elevation);
  • flat:所有面板高度一致、无额外间距,呈现扁平外观。

面板的_hasSpacing()方法正是判断「处于展开态且 accordion 的 displayMode 为 default」来决定是否添加mat-expansion-panel-spacingclass(见 expansion-panel.ts),host 绑定见 expansion-panel.ts。

5.3 批量展开/收起与键盘导航

手风琴容器还暴露了编程式 API。在组件模板上通过#accordion引用matAccordion导出名(exportAs: 'matAccordion',见 accordion.ts),即可调用openAll()/closeAll()

<mat-accordion #accordion="matAccordion"> ... </mat-accordion> <div class="example-action-buttons"> <button matButton (click)="accordion.openAll()">Expand All</button> <button matButton (click)="accordion.closeAll()">Collapse All</button> </div>

对应示例见 expansion-expand-collapse-all-example.html。此外,MatAccordion内部使用 CDK 的FocusKeyManager管理各面板 Header 的键盘焦点,支持方向键循环移动(withWrap())以及 Home/End 跳转(withHomeAndEnd()),实现见 accordion.ts。

六、懒渲染:ng-template 延迟初始化

默认情况下,即使面板处于折叠状态,其内容也会被初始化。如果希望把内容初始化推迟到面板首次展开时,需要把内容放进<ng-template matExpansionPanelContent>

<mat-expansion-panel> <mat-expansion-panel-header> This is the expansion title </mat-expansion-panel-header> <ng-template matExpansionPanelContent> Some deferred content </ng-template> </mat-expansion-panel>

其底层原理是 Portal 机制:MatExpansionPanelContent指令被@ContentChild捕获(见 expansion-panel.ts),面板通过opened事件流配合startWith(null)filter(() => this.expanded && !this._portal)take(1),在首次打开时把模板包成TemplatePortal挂载到ViewContainerRef上(见 expansion-panel.ts)。模板中的cdkPortalOutlet负责最终渲染(见 expansion-panel.html)。

这一特性对内容较重、数量较多的手风琴(如 FAQ、设置项分组)很有价值:折叠状态下不创建内容组件,减少初始渲染开销。

七、可访问性与交互细节

7.1 模拟原生 details/summary

MatExpansionPanel在无障碍层面模拟原生<details>/<summary>的体验。具体实现(见 expansion-panel-header.ts):

  • Header 上设置role="button"
  • 通过aria-controls指向内容区元素的 ID,_getPanelId()返回面板的id
  • 动态维护aria-expandedaria-disabled属性;
  • 面板内容区使用role="region"并带有aria-labelledby指向 Header ID(见 expansion-panel.html),保证屏幕阅读器能正确关联标题与内容;
  • 面板正文区域在折叠时通过inert属性从可访问性树中移除(见 expansion-panel.html),避免折叠内容中的控件仍可被聚焦。

7.2 键盘交互

Header 支持键盘操作(见 expansion-panel-header.ts):按SpaceEnter键(且未按住修饰键)即切换展开状态;其他方向键事件交由 accordion 的键盘管理器处理,实现面板间的焦点移动。同时,当面板折叠导致内部元素失去焦点时,组件会通过FocusMonitor把焦点程序化地归还给 Header(见 expansion-panel-header.ts)。

7.3 避免嵌套交互控件

不要把按钮、链接等交互控件放进<mat-expansion-panel-header>内部。因为 Header 本身就是按钮语义(role="button"),在其中嵌套交互元素会造成嵌套交互控件,破坏键盘导航与屏幕阅读器的体验,也容易引发事件冲突。工具栏、操作按钮请使用正文内容或mat-action-row承载。

八、状态事件与编程控制

MatExpansionPanel对外提供完整的编程接口与事件(见 expansion-panel.ts):

成员类型说明
expanded输入/状态面板是否展开
disabled输入是否禁用(继承自CdkAccordionItem
opened/closed事件展开/折叠状态变化(动画前)
afterExpand/afterCollapse输出动画完成后触发
toggle()/open()/close()方法编程式切换/展开/折叠

其中afterExpand/afterCollapse的触发依赖监听transitionend事件并校验grid-template-rows属性变化(见 expansion-panel.ts),即面板正文高度动画通过 CSS Grid 行高过渡实现;当全局动画被禁用(如prefers-reduced-motion或测试环境)时,则退化为直接订阅opened/closed立即派发。示例中「自感知面板」正是通过(opened)/(closed)更新状态文本(见 expansion-overview-example.html)。

九、默认配置全局定制

如果希望项目内所有展开面板共享某套默认值(如统一隐藏切换图标、固定 Header 高度),可以通过MAT_EXPANSION_PANEL_DEFAULT_OPTIONS注入令牌覆盖默认选项(定义见 expansion-panel.ts):

import {MAT_EXPANSION_PANEL_DEFAULT_OPTIONS} from '@angular/material/expansion'; providers: [ { provide: MAT_EXPANSION_PANEL_DEFAULT_OPTIONS, useValue: { collapsedHeight: '40px', expandedHeight: '64px', hideToggle: false, }, }, ],

面板构造时会读取该令牌并应用其中的hideToggle(见 expansion-panel.ts),Header 则应用expandedHeightcollapsedHeight(见 expansion-panel-header.ts)。

十、源码结构与进一步阅读

Expansion 模块的源码集中在 src/material/expansion 目录下,核心文件分工如下:

  • expansion-panel.ts:面板组件主体,负责状态、懒渲染 Portal、动画事件与默认配置;
  • expansion-panel-header.ts:标题栏组件及标题/描述指令,负责交互、焦点与 ARIA 属性;
  • accordion.ts:手风琴容器指令,负责互斥、批量操作与键盘导航;
  • accordion-base.ts:displayMode/togglePosition类型与MAT_ACCORDION注入令牌;
  • expansion-panel.html / expansion-panel-header.html:组件模板;
  • testing/expansion-harness.ts:组件测试 Harness,便于在测试中操作面板;
  • 行为验证可参考 expansion.spec.ts 与 accordion.spec.ts。

配套的完整可运行示例位于 src/components-examples/material/expansion,覆盖基础用法(expansion-overview)、分步向导(expansion-steps)、批量展开收起(expansion-expand-collapse-all)与测试 Harness 使用(expansion-harness)。

总结

mat-expansion-panelmat-accordion是一对高复用度的内容收纳组件:单面板负责「摘要 + 详情」的展开折叠,手风琴负责多面板的组织与互斥。通过hideToggletogglePositiondisplayModedisabledmulti等输入可以灵活定制外观与行为,mat-action-row支持分步式操作流程,matExpansionPanelContent模板指令实现懒渲染,而完整继承原生<details>/<summary>语义的无障碍实现保证了键盘与屏幕阅读器的友好体验。结合本仓库源码阅读,可以更准确地理解每个 API 背后的事件时序、动画机制与可访问性细节,进而在真实项目中用得精准、改得放心。

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

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

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

1.0.5.A 速通S32K312 Fls Flash Driver

Fls的配置与调试打开S32DS中包含的Example。双击mex文件&#xff0c;来到引脚配置界面。在引脚配置界面&#xff0c;先更新生成一下配置代码。然后回到代码界面&#xff0c;配置代码已经生成好了。打开主函数看看。去外设配置界面&#xff0c;看看和Fls有关系的配置。外设界面显…

作者头像 李华
网站建设 2026/9/12 18:23:56

JSP+SQL网上书店项目反编译还原与Tomcat部署实战

简介&#xff1a;JSPSQL网上书店项目是一套适合毕业设计及个人技术研究的完整源码与论文资料&#xff0c;覆盖图书展示、购物车、订单管理等典型业务模块&#xff0c;既可作为学生毕设参考&#xff0c;也适合个人学习或小规模项目二次开发。压缩包共436个文件&#xff0c;容量3…

作者头像 李华
网站建设 2026/9/12 18:23:37

从魔术方法到POP链:PHP反序列化漏洞原理与实战防御

我第一次在CTF里遇到PHP反序列化题目时&#xff0c;整个人是懵的。一串带着花括号的字符串&#xff0c;解码后竟然能直接执行系统命令&#xff0c;当时的我盯着payload看了半天&#xff0c;愣是没明白它是怎么跑起来的。后来在真实代码审计里反复碰到类似问题&#xff0c;又啃了…

作者头像 李华
网站建设 2026/9/12 18:23:07

LLM Agents技术解析:从原理到实战应用

1. LLM Agents&#xff1a;AI领域的新一代技术范式最近半年&#xff0c;LLM Agents&#xff08;大型语言模型智能体&#xff09;正在成为AI领域最炙手可热的研究方向。与传统的单一任务模型不同&#xff0c;LLM Agents通过赋予大语言模型规划、记忆和工具使用能力&#xff0c;正…

作者头像 李华
网站建设 2026/9/12 18:22:13

5分钟自托管NocoDB:可视化数据库完整指南

5分钟自托管NocoDB&#xff1a;可视化数据库完整指南 【免费下载链接】nocodb &#x1f525; &#x1f525; &#x1f525; A Free & Self-hostable Airtable Alternative 项目地址: https://gitcode.com/GitHub_Trending/no/nocodb 客户数据散落在十几个Excel里&am…

作者头像 李华
网站建设 2026/9/12 18:21:23

自动驾驶多传感器原始数据回放:高精度采集与可复现验证关键技术

1. 项目概述&#xff1a;为什么“原始数据回放”不是简单播个视频&#xff0c;而是自动驾驶验证的生死线“多路传感器原始数据回放&#xff1a;自动驾驶采集‑回放一体化设备选型解析”——这个标题里藏着一个被很多团队低估的硬核事实&#xff1a;在自动驾驶系统开发中&#x…

作者头像 李华