Angular的核心思想之一就是:組件化。組件化可以使我們的代碼更好的複用。
在使用官方提供的Angular庫Angular Material時,細心的同學就會發現,Material的每一個組件都有它自己樣式,如:
- 按鈕:
mat-button
- 工具條:
mat-toolbar
- 表格:
mat-table
- etc.
每個組件添加自己獨有的樣式,增加css作用域的控制,實現了樣式的隔離。
那麼,如果給一個自定義組件添加默認樣式呢?接下來我們介紹三種方法來實現我們的目標。
方法一:host
在組件的@Component
裝飾器中提供了host
屬性,該屬性可以爲我們提供很多功能的支持,其中一項就是給組件添加樣式。
以Material中的Table爲例:
@Component({
moduleId: module.id,
selector: 'mat-table, table[mat-table]',
exportAs: 'matTable',
template: CDK_TABLE_TEMPLATE,
styleUrls: ['table.css'],
host: {
'class': 'mat-table',
},
providers: [{provide: CdkTable, useExisting: MatTable}],
encapsulation: ViewEncapsulation.None,
// See note on CdkTable for explanation on why this uses the default change detection strategy.
// tslint:disable-next-line:validate-decorators
changeDetection: ChangeDetectionStrategy.Default,
})
export class MatTable<T> extends CdkTable<T> {
/** Overrides the sticky CSS class set by the `CdkTable`. */
protected stickyCssClass = 'mat-table-sticky';
}
在MatTable的源碼中,我們可以看到爲host屬性設置了'class': 'mat-table'
,在我們使用MatTable組件時,就會添加上默認的樣式: mat-table
.
注意
雖然在Angular中提供了host屬性,並且官方的Material庫也是使用該屬性實現了很多功能,但是,在Angular編碼規範中卻不推薦使用該方法。詳見:HostListener 和 HostBinding 裝飾器 vs. 組件元數據 host
方法二:HostBinding
如方法一中注意事項中提到的,官方不推薦使用host
屬性,推薦使用@HostBinding
裝飾器來實現host
的關於dom屬性相關的功能。
還是以MatTable爲例,需要做一下改造來實現相應的功能:
@Component({
moduleId: module.id,
selector: 'mat-table, table[mat-table]',
exportAs: 'matTable',
template: CDK_TABLE_TEMPLATE,
styleUrls: ['table.css'],
// host: {
// 'class': 'mat-table',
// },
providers: [{provide: CdkTable, useExisting: MatTable}],
encapsulation: ViewEncapsulation.None,
// See note on CdkTable for explanation on why this uses the default change detection strategy.
// tslint:disable-next-line:validate-decorators
changeDetection: ChangeDetectionStrategy.Default,
})
export class MatTable<T> extends CdkTable<T> {
/** Overrides the sticky CSS class set by the `CdkTable`. */
protected stickyCssClass = 'mat-table-sticky';
// 使用HostBinding裝飾器
@HostBinding('class.mat-table') clz = true;
}
方法三:Renderer2
Renderer2
是Angular的渲染引擎,我們可以通過它來爲自定義組件添加默認樣式。
還是以MatTable爲例,需要做一下改造來實現相應的功能:
@Component({
moduleId: module.id,
selector: 'mat-table, table[mat-table]',
exportAs: 'matTable',
template: CDK_TABLE_TEMPLATE,
styleUrls: ['table.css'],
// host: {
// 'class': 'mat-table',
// },
providers: [{provide: CdkTable, useExisting: MatTable}],
encapsulation: ViewEncapsulation.None,
// See note on CdkTable for explanation on why this uses the default change detection strategy.
// tslint:disable-next-line:validate-decorators
changeDetection: ChangeDetectionStrategy.Default,
})
export class MatTable<T> extends CdkTable<T> {
/** Overrides the sticky CSS class set by the `CdkTable`. */
protected stickyCssClass = 'mat-table-sticky';
constructor(render: Renderer2, eleRef: ElementRef) {
render.addClass(eleRef.nativeElement, 'mat-table');
}
}
總結
很多時候,實現一個功能的方法有很多,需要我們不斷的去挖掘,去思考。條條大路通羅馬,只要努力了總會有收穫。