Angular 11:如何在Mat Menu完全渲染后执行代码测量高度?
方案1:用setTimeout延迟执行(简单高效)
menuOpened触发时菜单已插入DOM,但浏览器可能还未完成样式渲染,用0延迟的setTimeout能让浏览器先处理完当前渲染队列,再执行高度测量:
<img src="assets/img/info.svg" #menuTrigger="matMenuTrigger" [matMenuTriggerFor]="menu" (menuOpened)="menuOpened(menu)"> <mat-menu #menu="matMenu"> </mat-menu>
menuOpened(menu: MatMenu) { setTimeout(() => { const menuPanel = menu._elementRef.nativeElement.querySelector('.mat-menu-panel'); if (menuPanel) { const height = (menuPanel as HTMLElement).offsetHeight; console.log('菜单实际高度:', height); // 这里执行你的高度相关业务逻辑 } }, 0); }
方案2:用requestAnimationFrame(更贴合渲染周期)
利用浏览器的渲染帧回调,确保在页面重绘完成后执行测量,比setTimeout更贴合浏览器渲染逻辑:
menuOpened(menu: MatMenu) { requestAnimationFrame(() => { const menuPanel = menu._elementRef.nativeElement.querySelector('.mat-menu-panel'); if (menuPanel) { const height = (menuPanel as HTMLElement).clientHeight; console.log('菜单内容高度:', height); } }); }
方案3:监听transitionend事件(适配带动画的菜单)
如果你的Mat Menu启用了入场动画,可直接监听动画结束事件,确保菜单完全展开后再测量:
menuOpened(menu: MatMenu) { const menuPanel = menu._elementRef.nativeElement.querySelector('.mat-menu-panel'); if (menuPanel) { const handleTransitionEnd = () => { const height = (menuPanel as HTMLElement).offsetHeight; console.log('动画完成后菜单高度:', height); menuPanel.removeEventListener('transitionend', handleTransitionEnd); }; menuPanel.addEventListener('transitionend', handleTransitionEnd); } }
额外提示
- 若不想依赖
_elementRef私有属性,可改用ViewChild获取菜单实例:
import { ViewChild } from '@angular/core'; import { MatMenu } from '@angular/material/menu'; @ViewChild('menu') menu!: MatMenu; menuOpened() { setTimeout(() => { const menuPanel = this.menu._elementRef.nativeElement.querySelector('.mat-menu-panel'); // 测量逻辑... }, 0); }
offsetHeight包含元素边框,clientHeight仅包含内容+内边距,按需选择测量属性。
内容的提问来源于stack exchange,提问作者LoveAllThingsCode
相关产品推荐
相关产品推荐

