如何解决Angular Material mat-dialog中绝对定位列表启动跳变问题
故障根因
mat-dialog默认会先渲染DOM结构、再执行入场动画、最后计算容器最终尺寸,你的字母索引容器设置了绝对定位,但父级mat-dialog-content未明确声明position: relative,初始渲染时绝对定位的参考节点是未完成尺寸计算的上层dialog容器,等容器尺寸稳定后参考节点切换为mat-dialog-content,就会出现位置跳动的问题。
修复方案
- 第一步:给
mat-dialog-content明确添加相对定位规则,让字母索引从渲染初始就以它为定位参考 - 第二步:简化绝对定位的属性配置,避免同时设置上下左右四个偏移值导致的布局计算冲突
- 第三步:可选:监听dialog打开完成事件后再渲染字母索引,彻底规避入场动画阶段的布局抖动
代码修改示例
弹窗组件TS文件
import { MatDialogRef } from '@angular/material/dialog'; // 组件内部属性 dialogInitComplete = false; constructor(public dialogRef: MatDialogRef<CompanySelectionDialog>) {} ngOnInit() { // 监听dialog入场动画完成、尺寸稳定后再显示字母索引 this.dialogRef.afterOpened().subscribe(() => { this.dialogInitComplete = true; }); }
弹窗HTML文件
<!-- 给mat-dialog-content添加position: relative --> <mat-dialog-content style="position: relative;"> <div *ngFor="let companies of this.companiesSortedByLetter" style="width: 95%"> <!-- 原有企业列表代码保持不变 --> <mat-toolbar [id]="companies.letter"> <span>{{ companies.letter.toUpperCase() }}</span> </mat-toolbar> <mat-selection-list #companies [multiple]="false" [(ngModel)]="selectedCompany"> <mat-list-option ngDefaultControl *ngFor="let sortedCompany of companies.companies" [value]="sortedCompany" mat-dialog-close (click)="onSelect(selectedCompany[0])"> {{ sortedCompany.Description + ' ' + sortedCompany.ID }} </mat-list-option> </mat-selection-list> </div> <!-- 简化定位规则,dialog初始化完成后再渲染 --> <div *ngIf="dialogInitComplete" style="position: absolute; right: 12px; top: 20px; width: 40px; z-index: 100;"> <mat-list> <mat-list-item class="alphaList" ontouchmove="console.log('moved')" matRipple *ngFor="let letter of this.companiesSortedByLetter" (click)="scrollToLetter(letter.letter)">{{ letter.letter.toUpperCase() }} </mat-list-item> </mat-list> </div> </mat-dialog-content>
global.scss修改
.companySelectionPanel { // 强制给dialog内容容器添加相对定位,避免默认样式覆盖 mat-dialog-content { position: relative !important; } .alphaList { @media screen and (max-height: 1024px) { height: 30px !important } @media screen and (min-height: 1366px) { height: 38px !important } } }
额外优化建议
如果调整后仍有轻微抖动,可直接使用position: sticky替代绝对定位,不需要依赖父级相对定位,直接将字母索引固定在可视区域右侧,滚动时也不会偏移:
.alpha-index-wrapper { position: sticky; float: right; top: 20px; width: 40px; z-index: 100; }
内容的提问来源于stack exchange,提问作者Elliott Ives
相关产品推荐
相关产品推荐

