Angular Material mat-select动态样式实现及::ng-deep替代方案咨询
问题根因
.mat-select-panel样式失效的原因:mat-select 的下拉面板默认挂载在全局<body>下的cdk-overlay-container容器中,不属于当前组件的DOM子树,因此组件内基于父容器类名的层级选择器无法匹配到独立在外的面板元素。::ng-deep废弃后的替代方案:Angular 目前推荐两种无副作用的样式覆盖方案,一是写全局样式配合专属类名避免污染,二是给组件设置ViewEncapsulation.None取消样式隔离,同样配合专属类名使用。
实现步骤
- 动态绑定下拉面板类名
给mat-select的panelClass做动态绑定,根据选择状态切换面板的类,解决面板样式匹配问题:
// 组件ts文件中新增计算属性 get selectPanelClass() { const baseClass = 'dialog-selection-box'; return this.selectionSuccessful ? `${baseClass} dialog-selection-box-success` : baseClass; }
<!-- 模板中修改mat-select的panelClass属性 --> <mat-select [panelClass]="selectPanelClass" [(ngModel)]="tableName" (ngModelChange)="onTableChange()"> <mat-option *ngFor="let table of tableNames" [value]="table"> {{ table }} </mat-option> </mat-select>
- 调整样式实现
选择以下两种方案之一即可替代::ng-deep:
方案一:全局样式(更推荐,无组件侵入)
把所有自定义样式放到项目全局的styles.scss中,所有样式都加专属前缀,不会污染其他组件:
// 基础状态表单样式 .table-select-selection { $default-color: rgb(168, 168, 168); .mat-form-field-infix { font-size: 16px; padding-left: 5px !important; } .mat-select-arrow { color: $default-color !important; } .mat-form-field { width: 100%; .mat-input-element { color: $default-color !important; } .mat-form-field-label { color: $default-color !important; margin: 5px; } .mat-form-field-underline, .mat-form-field-ripple { background-color: $default-color !important; } } } // 基础状态下拉面板样式 .dialog-selection-box { $default-color: rgb(168, 168, 168); .mat-option[aria-selected="true"] { color: $default-color !important; } .mat-option-text:hover { font-weight: bold !important; } } // 成功状态表单样式 .table-select-selection-success { $success-color: green; .mat-form-field-infix { background-color: rgba(0, 128, 0, 0.25); } .mat-select-arrow { color: $success-color !important; } .mat-form-field { .mat-input-element, .mat-form-field-label { color: $success-color !important; } .mat-form-field-underline, .mat-form-field-ripple { background-color: $success-color !important; } } } // 成功状态下拉面板样式 .dialog-selection-box-success { $success-color: green; .mat-option[aria-selected="true"] { color: $success-color !important; } }
方案二:组件内取消样式隔离
在组件的@Component装饰器中添加encapsulation: ViewEncapsulation.None配置,之后把上面的样式直接写在组件的scss文件中即可,不需要加::ng-deep。
内容的提问来源于stack exchange,提问作者norsemanGrey
相关产品推荐
相关产品推荐

