Angular使用ng-template实现Material递归mat-menu渲染异常求助
问题根因
你代码的核心问题出在子菜单存在性判断逻辑错误,其次可补充触发配置优化交互:
- 你给所有
MenuItem都默认定义了children: []空数组,而JS中空数组属于真值,所以原判断*ngIf="parentItem.children"永远成立,所有菜单项都会走带子菜单的menuItem模板,哪怕实际没有子项,导致空的mat-menu绑定引发渲染异常。 - 未显式配置子菜单悬浮触发逻辑,部分版本Angular Material默认仅支持点击触发嵌套菜单。
修复方案
步骤1:修正子菜单判断条件
把所有子项存在性判断改为校验children数组长度,空数组会被判定为无有效子项,走普通菜单项逻辑。
步骤2:(可选)添加悬浮触发配置
给子菜单触发按钮添加matMenuTriggerHoverDelay配置,实现hover自动弹出子菜单,符合常规菜单交互习惯。
步骤3:(可选)配置子菜单不覆盖父菜单
给mat-menu添加[overlapTrigger]="false"属性,避免子菜单弹出时遮挡父菜单、触发父菜单关闭。
修改后的完整模板代码
<button mat-button [matMenuTriggerFor]="itemMenu"> {{ startMenuItem.description }} </button> <mat-menu #itemMenu="matMenu" [overlapTrigger]="false"> <ng-container *ngFor="let childItem of startMenuItem.children"> <ng-container *ngTemplateOutlet="recursiveMenuTmpl; context: { $implicit: childItem }" > </ng-container> </ng-container> </mat-menu> <ng-template #recursiveMenuTmpl let-parentItem> <!-- 修正判断逻辑:只有children长度大于0才识别为有子菜单 --> <ng-container *ngIf="parentItem.children?.length > 0"> <ng-container *ngTemplateOutlet="menuItem; context: { $implicit: parentItem }" ></ng-container> </ng-container> <ng-container *ngIf="!parentItem.children?.length"> <ng-container *ngTemplateOutlet="singleItem; context: { $implicit: parentItem }" ></ng-container> </ng-container> </ng-template> <ng-template #menuItem let-rootItem> <!-- 添加悬浮触发延迟,单位ms,可自行调整数值 --> <button [matMenuTriggerFor]="itemMenu" mat-menu-item [matMenuTriggerHoverDelay]="150"> {{ rootItem.description }} </button> <mat-menu #itemMenu="matMenu" [overlapTrigger]="false"> <ng-container *ngFor="let childItem of rootItem.children"> <ng-container *ngTemplateOutlet="recursiveMenuTmpl; context: { $implicit: childItem }" > </ng-container> </ng-container> </mat-menu> </ng-template> <ng-template #singleItem let-item> <button *ngIf="item.route" mat-menu-item [routerLink]="item.uri"> {{ item.description }} </button> <button *ngIf="!item.route" mat-menu-item (click)="onOpenUrl(item.uri)"> {{ item.description }} </button> </ng-template>
补充注意事项
请确保你已经在对应模块中导入了以下依赖:
MatMenuModuleMatButtonModuleRouterModule(如果使用路由跳转功能)
修改后原本缺失的子菜单展开箭头会自动渲染,hover即可弹出子菜单且父菜单不会自动关闭。
内容的提问来源于stack exchange,提问作者Jeroen
相关产品推荐
相关产品推荐

