通常情况下,要为某个元素添加指定样式,我们可以直接这样做:
<button class="btn btn-primary">提交</button>
但某些时候我们需要根据不同的条件,为指定元素应用不同的样式。对于这种场景,我们可以使用属性绑定,如:
<button class="btn" [class.btn-primary]="true" type="submit">
提交
</button>
但有时候,一个元素可能拥有多种状态样式,这时我们就可以使用 ngClass
指令。传递给 ngClass 指令的表达式的数据类型可以是:对象、数组或字符串。
接下来让我们来分别看一下具体的使用示例:
<button [ngClass]="['btn', 'btn-primary']">提交</button>
Angular 将会接收传递给 ngClass 指令的样式数组,然后把对应的样式应用到指定的元素上。下面是最终显示结果:
<button class="btn btn-primary">提交</button>
<button [ngClass]="'btn btn-primary'" type="submit" (click)="submit()">
提交
</button>
<button [ngClass]="{ btn: true, 'btn-primary': true }">
提交
</button>
样式配置对象的键为样式类的名称,而对应的值是布尔值或布尔表达式,即用于表示是否应用对应的样式类。
@Component({
selector: 'app-root',
template: `
<button (click)="toggleState()">切换状态</button>
<button [ngClass]="calculateClasses()" (click)="submit()">
提交
</button>
`})
export class AppComponent {
stateFlag = false;
toggleState() {
this.stateFlag = !this.stateFlag;
}
submit() {
console.log('Button submitted');
}
calculateClasses() {
return {
btn: true,
'btn-primary': true,
'btn-extra-class': this.stateFlag
};
}
}
<button [ngStyle]="{background: 'red'}">提交</button>
以下是最终的显示结果:
<button style="background: red">提交</button>
类似于 ngClass 综合示例的使用方式,当 ngStyle 指令的配置对象过大,我们可以通过组件的方法来获取样式配置对象,比如:
<button [ngStyle]="calculateStyles()">提交</button>
app.component.html
@Component({
selector: 'my-app',
styleUrls:['./app.component.css'],
template: `
<button class="red-button">Button</button>
`})
export class AppComponent {}
app.component.css
.red-button {
background:red;
}
以上代码成功运行后,页面生成的 HTML 结构:
<my-app _nghost-c12="" ng-version="6.0.0">
<button _ngcontent-c12="" class="red-button">按钮1</button>
</my-app>
<button class="red-button">按钮2</button>
当你看到页面的显示结果,你可能会感到惊讶,按钮2
的背景颜色没有变成红色,这时我们来查看一下模板内红色按钮所应用的样式:
.red-button[_ngcontent-c12] {
background:red;
}
除此之外,从页面生成的 HTML 结构,我们也发现了 _nghost-c12
、_ngcontent-c12
这些奇怪的属性。
那么这些属性是什么呢,它们有什么用?为了弄清楚这些属性,我们再新建一个 BlueButtonComponent 组件,代码如下:
@Component({
selector: 'blue-button',
template: `
<h3>蓝色按钮组件</h3>
<button class="blue-button">蓝色按钮</button>
`,
styles: [`
.blue-button {
background:blue;
}
`]
})
export class BlueButtonComponent { }
之后,我们在根组件中使用新建的 BlueButtonComponent 组件:
@Component({
selector: 'my-app',
styleUrls:['./app.component.css'],
template: `
<button class="red-button">红色按钮</button>
<blue-button></blue-button>
`})
export class AppComponent { }
以上代码成功运行后,页面生成以下 HTML 代码:
<my-app _nghost-c17="" ng-version="6.0.0">
<button _ngcontent-c17="" class="red-button">红色按钮</button>
<blue-button _ngcontent-c17="" _nghost-c18="">
<h2 _ngcontent-c18="">蓝色按钮组件</h2>
<button _ngcontent-c18="" class="blue-button">蓝色按钮</button>
</blue-button>
</my-app>
我们注意到 blue-button
元素,新增了 _nghost-c18
host 属性,另外也存在一个 _ngcontent-c17
属性。
_nghost-c0
, _nghost-c1
。_ngcontent-c0
, _ngcontent-c1
。然而这些属性,是如何启动视图封装的作用呢?
/* Style 1 - a simple CSS style,
with low specificy and easilly overridable */
.blue-button {
background: blue;
}
/* Style 2 - a similar style, with a much higher
specificity and much harder to override */
.blue-button[_ngcontent-c1] {
background: blue;
}
有些时候,我们只想为宿主元素设置某些样式,但却不想影响到宿主元素下的其它元素。这时我们可以使用 :host
选择器:
/* styles applied directly to the ap-root element only */
:host {
border: 2px solid dimgray;
display: block;
padding: 20px;
}
通过 :host
选择器我们可以确保上面的样式只被应用到宿主元素上,:host
选择器在运行时会转换为以下样式:
<style>
[_nghost-c0] {
border: 2px solid dimgray;
display: block;
padding: 20px;
}
</style>
此外 :host
选择器也可以结合其它的选择器,比如:
/* let's add another style to app.conmponent.css */
:host h2 {
color: red;
}
以上样式在运行时,将生成以下样式:
<style>
....
[_nghost-c0] h2[_ngcontent-c0] {
color: red;
}
</style>
很明显,特定的作用域相关的属性,也会被应用到嵌入的选择器上,从而确保样式只局部应用于特定的模板。但如果我们想要设置所有 h2
标签的元素呢,这里仍有对应的方法。
:host ::ng-deep h2 {
color: red;
}
以上样式在运行时,将生成以下样式:
[_nghost-c0] h2 {
color: red;
}
:host-context
伪类选择器对于开发主题样式很有用,示例如下:
@Component({
selector: 'themeable-button',
template: `
<button class="btn btn-theme">可配主题按钮</button>
`,
styles: [`
:host-context(.red-theme) .btn-theme {
background: red;
}
:host-context(.blue-theme) .btn-theme {
background: blue;
}
`]
})
export class ThemeableButtonComponent { }
ThemeableButtonComponent 的使用示例如下:
<div class="blue-theme">
<themeable-button></themeable-button>
</div>