掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Angular 應(yīng)用使用標(biāo)準(zhǔn)的 CSS 來(lái)設(shè)置樣式。這意味著你可以把關(guān)于 CSS 的那些知識(shí)和技能直接用于 Angular 程序中,例如:樣式表、選擇器、規(guī)則以及媒體查詢等。

另外,Angular 還能把組件樣式捆綁在組件上,以實(shí)現(xiàn)比標(biāo)準(zhǔn)樣式表更加模塊化的設(shè)計(jì)。
本章將會(huì)講解如何加載和使用這些組件樣式。
可以運(yùn)行現(xiàn)場(chǎng)演練 / 下載范例,在 Stackblitz 中試用并下載本頁(yè)的代碼。
對(duì)你編寫(xiě)的每個(gè) Angular 組件來(lái)說(shuō),除了定義 HTML 模板之外,還要定義用于模板的 CSS 樣式、 指定任意的選擇器、規(guī)則和媒體查詢。
實(shí)現(xiàn)方式之一,是在組件的元數(shù)據(jù)中設(shè)置 ?styles ?屬性。 ?styles ?屬性可以接受一個(gè)包含 CSS 代碼的字符串?dāng)?shù)組。 通常你只給它一個(gè)字符串就行了,如同下例:
@Component({
selector: 'app-root',
template: `
Tour of Heroes
`,
styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}在 ?
@Component? 的元數(shù)據(jù)中指定的樣式只會(huì)對(duì)該組件的模板生效。
它們既不會(huì)被模板中嵌入的組件繼承,也不會(huì)被通過(guò)內(nèi)容投影(如 ng-content)嵌進(jìn)來(lái)的組件繼承。
在這個(gè)例子中,?h1? 的樣式只對(duì) ?HeroAppComponent ?生效,既不會(huì)作用于內(nèi)嵌的 ?HeroMainComponent?,也不會(huì)作用于應(yīng)用中其它任何地方的 ?? 標(biāo)簽。
這種范圍限制就是所謂的樣式模塊化特性
組件樣式中有一些從影子(Shadow) DOM 樣式范圍領(lǐng)域(記錄在W3C的CSS Scoping Module Level 1中) 引入的特殊選擇器:
每個(gè)組件都會(huì)關(guān)聯(lián)一個(gè)與其組件選擇器相匹配的元素。這個(gè)元素稱(chēng)為宿主元素,模板會(huì)渲染到其中。?:host? 偽類(lèi)選擇器可用于創(chuàng)建針對(duì)宿主元素自身的樣式,而不是針對(duì)宿主內(nèi)部的那些元素。
@Component({
selector: 'app-main',
template: `
It Works!
Start editing to see some magic happen :)
`
})
export class HostSelectorExampleComponent {
}下面的樣式將以組件的宿主元素為目標(biāo)。應(yīng)用于此選擇器的任何規(guī)則都將影響宿主元素及其所有后代(在這種情況下,將所有包含的文本斜體)。(譯注:后代的樣式源自 CSS 的樣式繼承特性)
:host {
font-style: italic;
}?:host? 選擇是是把宿主元素作為目標(biāo)的唯一方式。除此之外,你將沒(méi)辦法指定它, 因?yàn)樗拗鞑皇墙M件自身模板的一部分,而是父組件模板的一部分。
要把宿主樣式作為條件,就要像函數(shù)一樣把其它選擇器放在 ?:host? 后面的括號(hào)中。
在這個(gè)例子中,當(dāng) CSS 類(lèi) ?active ?應(yīng)用在宿主元素上時(shí),宿主元素的內(nèi)容也變成了粗體。
:host {
font-style: italic;
}
:host(.active) {
font-weight: bold;
}?:host? 選擇器也可以與其他選擇器組合使用。在 ?:host? 后面添加選擇器以選擇子元素,例如,使用 ?:host h2? 定位組件視圖內(nèi)的 ??。
不應(yīng)該在 ?
:host? 選擇器前面添加除 ?
:host-context? 之外的選擇器來(lái)試圖基于組件視圖的外部上下文為本組件設(shè)置樣式。因?yàn)榇祟?lèi)選擇器的作用域不會(huì)限于組件的視圖,而是會(huì)選擇外部上下文,但這不是內(nèi)置的行為。請(qǐng)改用 ?
:host-context? 選擇器。
有時(shí)候,需要以某些來(lái)自宿主的祖先元素為條件來(lái)決定是否要應(yīng)用某些樣式。 例如,在文檔的 ?? 元素上可能有一個(gè)用于表示樣式主題 (theme) 的 CSS 類(lèi),你應(yīng)當(dāng)基于它來(lái)決定組件的樣式。
這時(shí)可以使用 ?:host-context()? 偽類(lèi)選擇器。它也以類(lèi)似 ?:host()? 形式使用。它在當(dāng)前組件宿主元素的祖先節(jié)點(diǎn)中查找 CSS 類(lèi), 直到文檔的根節(jié)點(diǎn)為止。它只能與其它選擇器組合使用。
在下面的例子中,只有當(dāng)該組件的某個(gè)祖先元素有 CSS 類(lèi) ?active ?時(shí),才會(huì)把該組件內(nèi)部的所有文本置為斜體。
:host-context(.active) {
font-style: italic;
}注意,只有宿主元素及其各級(jí)子節(jié)點(diǎn)會(huì)受到影響,不包括加上 ?active ?類(lèi)的這個(gè)節(jié)點(diǎn)的祖先。
組件樣式通常只會(huì)作用于組件自身的 HTML 上。
把偽類(lèi) ?::ng-deep? 應(yīng)用到任何一條 CSS 規(guī)則上就會(huì)完全禁止對(duì)那條規(guī)則的視圖包裝。任何帶有 ?::ng-deep? 的樣式都會(huì)變成全局樣式。為了把指定的樣式限定在當(dāng)前組件及其下級(jí)組件中,請(qǐng)確保在 ?::ng-deep? 之前帶上 ?:host? 選擇器。如果 ?::ng-deep? 組合器在 ?:host? 偽類(lèi)之外使用,該樣式就會(huì)污染其它組件。
這個(gè)例子以所有的 ?? 元素為目標(biāo),從宿主元素到當(dāng)前元素再到 DOM 中的所有子元素:
:host ::ng-deep h3 {
font-style: italic;
}?/deep/? 組合器還有兩個(gè)別名:?>>>? 和 ?::ng-deep?。
?
/deep/? 和 ?>>>? 選擇器只能被用在仿真 (emulated) 模式下。 這種方式是默認(rèn)值,也是用得最多的方式。
CSS 標(biāo)準(zhǔn)中用于 "刺穿 Shadow DOM" 的組合器已經(jīng)被棄用,并將 這個(gè)特性從主流瀏覽器和工具中移除。 因此,我們也將在 Angular 中移除對(duì)它們的支持(包括 ?
/deep/?、?
>>>? 和 ?
::ng-deep?)。 目前,建議先統(tǒng)一使用 ?
::ng-deep?,以便兼容將來(lái)的工具。
有幾種方式把樣式加入組件:
styles ?或 ?styleUrls ?元數(shù)據(jù)上述作用域規(guī)則對(duì)所有這些加載模式都適用。
給 ?@Component? 裝飾器添加一個(gè) ?styles ?數(shù)組型屬性。
這個(gè)數(shù)組中的每一個(gè)字符串(通常也只有一個(gè))定義一份 CSS。
@Component({
selector: 'app-root',
template: `
Tour of Heroes
`,
styles: ['h1 { font-weight: normal; }']
})
export class HeroAppComponent {
/* . . . */
}注意:這些樣式只對(duì)當(dāng)前組件生效。 它們既不會(huì)作用于模板中嵌入的任何組件,也不會(huì)作用于投影進(jìn)來(lái)的組件(如 ?
ng-content? )。
當(dāng)使用 ?--inline-styles? 標(biāo)識(shí)創(chuàng)建組件時(shí),Angular CLI 的 ?ng generate component? 命令就會(huì)定義一個(gè)空的 ?styles ?數(shù)組
ng generate component hero-app --inline-style把外部 CSS 文件添加到 ?@Component? 的 ?styleUrls ?屬性中以加載外部樣式。
@Component({
selector: 'app-root',
template: `
Tour of Heroes
`,
styleUrls: ['./hero-app.component.css']
})
export class HeroAppComponent {
/* . . . */
}h1 {
font-weight: normal;
}注意:這些樣式只對(duì)當(dāng)前組件生效。 它們既不會(huì)作用于模板中嵌入的任何組件,也不會(huì)作用于投影進(jìn)來(lái)的組件(如 ?
ng-content? )。
你可以指定多個(gè)樣式文件,甚至可以組合使用 ?
style?和 ?styleUrls?方式。
當(dāng)你使用 Angular CLI 的 ?ng generate component? 命令但不帶 ?--inline-style? 標(biāo)志時(shí),CLI 會(huì)為你創(chuàng)建一個(gè)空白的樣式表文件,并且在所生成組件的 ?styleUrls ?中引用該文件。
ng generate component hero-app可以直接在組件的 HTML 模板中寫(xiě) ?? 標(biāo)簽來(lái)內(nèi)嵌 CSS 樣式。
@Component({
selector: 'app-hero-controls',
template: `
Controls
`
})你也可以在組件的 HTML 模板中寫(xiě) ?? 標(biāo)簽。
@Component({
selector: 'app-hero-team',
template: `
Team
-
{{member}}
`
})當(dāng)使用 CLI 進(jìn)行構(gòu)建時(shí),要確保這個(gè)鏈接到的樣式表文件被復(fù)制到了服務(wù)器上。
只要引用過(guò),CLI 就會(huì)計(jì)入這個(gè)樣式表,無(wú)論這個(gè) link 標(biāo)簽的 href 指向的 URL 是相對(duì)于應(yīng)用根目錄的還是相對(duì)于組件文件的。
可以利用標(biāo)準(zhǔn)的 CSS @import 規(guī)則來(lái)把其它 CSS 文件導(dǎo)入到 CSS 文件中。
在這種情況下,URL 是相對(duì)于你正在導(dǎo)入的 CSS 文件的。
/* The AOT compiler needs the `./` to show that this is local */
@import './hero-details-box.css';當(dāng)使用 CLI 進(jìn)行構(gòu)建時(shí),你必須配置 ?angular.json? 文件,使其包含所有外部資源(包括外部的樣式表文件)。
在它的 ?styles ?區(qū)注冊(cè)這些全局樣式文件,默認(rèn)情況下,它會(huì)有一個(gè)預(yù)先配置的全局 ?styles.css? 文件。
如果使用 CLI 進(jìn)行構(gòu)建,那么你可以用 sass 或 less 來(lái)編寫(xiě)樣式,并使用相應(yīng)的擴(kuò)展名(?.scss?、?.less?)把它們指定到 ?@Component.styleUrls? 元數(shù)據(jù)中。例子如下:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
...CLI 的構(gòu)建過(guò)程會(huì)運(yùn)行相關(guān)的預(yù)處理器。
當(dāng)使用 ?ng generate component? 命令生成組件文件時(shí),CLI 會(huì)默認(rèn)生成一個(gè)空白的 CSS 樣式文件(?.css?)。 你可以配置 CLI,讓它默認(rèn)使用你喜歡的 CSS 預(yù)處理器。
添加到 ?
@Component.styles? 數(shù)組中的字符串必須寫(xiě)成 CSS,因?yàn)?nbsp;CLI 沒(méi)法對(duì)這些內(nèi)聯(lián)的樣式使用任何 CSS 預(yù)處理器。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流