1.Angular樣式隔離
Angular樣式隔離的好處最最要的一條就是CSS的可維護性,當沒有樣式隔離時,我們創建一個組件并添加樣式后,可能會影響到其他的組件樣式,而且很有可能查找不出問題所在,雖然我們可以想出辦法來避免樣式被覆寫,但是可能會引發CSS的可維護性問題,
Angular的視圖封裝(View Encapsulation)
在Angular中,組件的樣式可以封裝在組件的宿主元素中(host),這樣它們就不會影回應用程式的其他部分,
視圖封裝模式:
1.ViewEncapsulation.ShadowDom: Angualr使用瀏覽器內置的Shadow Dom API將組件的視圖封裝在ShadowRoot中,用作組件的宿主元素,并以隔離的方式應用提供的樣式(只對瀏覽器內置Shadow Dom支持時才起作用),組件的樣式只添加到Shadow Dom宿主中,確保它們只影響各自組件視圖中的元素,
2.ViewEncapsulation.Emulated:使樣式僅應用于組件的視圖,不會影回應用程式中的其他元素,模擬Shadow Dom行為(默認的視圖封裝模式),組件的樣式被添加到檔案的<head>中,使它們在整個應用程式中可用,但只影響它們各自組件模板中的元素,
3.ViewEncapsulation.None:不使用任何型別的視圖封裝,為組件指定的任何樣式都是全域應用的,并且影回應用程式中的任何HTML元素,組建的樣式被添加到檔案的<head>中,使它們在整個應用程式中可用,所以時完全全域的,并影響檔案中的任務匹配元素,
要想設定組件的視圖封裝模式,可以在組件裝飾器中設定 encapsulation 選項,
為了更好的理解默認的視圖封裝(Emulated View Encapsulation)是如何起作用的,先貼上一段代碼:
1 @Component({ 2 selector: 'app-root', 3 template: ` 4 <h2>Parent Component</h2> 5 <app-child></app-child> 6 `, 7 styles: [ 8 ` 9 h2 { 10 background-color: lightskyblue; 11 } 12 ` 13 ], 14 encapsulation: ViewEncapsulation.Emulated 15 }) 16 export class AppComponent implements OnInit { 17 18 ... 19 }
1 @Component({ 2 selector: 'app-child', 3 template: ` 4 <h2>Child Component</h2> 5 `, 6 styles: [ 7 ` 8 h2 { 9 background-color: aqua; 10 } 11 ` 12 ], 13 encapsulation: ViewEncapsulation.Emulated 14 }) 15 export class ChildComponent implements OnInit { 16 17 ... 18 }
以下是運行時的代碼,

可以看到app-root自定義元素上添加了一個奇怪的屬性:_nghost-jtq-c16屬性;在根組件中的HTML元素有一個看起來很奇怪但不同的屬性:_ngcontent-jtq-c16;app-child自定義元素上添加了另一個屬性:_nghost-jtq-c17,以及組件內HTML元素有一個_ngcontent-jtq-c17屬性,
因此,我們可以知道Angular樣式隔離的基本原理:
1.在應用程式啟動時(或在使用AOT構建時),每個組件都將具有附加到宿主元素的唯一屬性,具體取決于組件的處理順序:_nghost-jtq-c16, _nghost-jtq-c17,
2.除此之外,每個組件模板中的每個元素也將應用該特定組件獨有的屬性:_ngcontent-jtq-c16, _ngcontent-jtq-c17,
Angular將這些樣式應用到相應的獨特屬性上:


2.選擇器(:host, :host-context, ::ng-deep)的使用
:host
每個組件都與一個和組件的選擇器相匹配的元素相關聯,呈現模板的這個元素稱為宿主元素,:host 偽類選擇器用于創建以宿主元素本身為目標的樣式,而不是以宿主內部的元素為目標,
當我們想要為app-root組件本身添加樣式(加一個邊框),就需要用到 :host 偽類選擇器,原因是所有與組件關聯的樣式(通過css檔案或行內形式在組件裝飾器中宣告),通常作用于模板內的元素,
1 :host { 2 display: block; 3 border: 5px solid palegreen; 4 }

應用樣式后,組件顯示入下:
:host與其他選擇器組合使用
1 :host h2 { 2 color: red; 3 }
1 :host(.active) { 2 font-weight: bold; 3 }
在:host()選擇器中,括號內的條件決定了要設定樣式的宿主元素(宿主元素具有active類),
::ng-deep
將::ng-deep偽類應用于任何CSS規則會完全禁止視圖封裝規則;任何應用了::ng-deep的樣式都會成為全域樣式,為了將指定樣式限定在當前組件以及后代,確保在::ng-deep之前包含:host選擇器,如果在沒有:host偽類選擇器的情況下使用::ng-deep選擇器,樣式可能會滲入其他組件,
如果希望組件的樣式級聯到組件的所有子元素,而不是頁面上的任務其他元素,我們可以通過將:host與::ng-deep選擇器結合使用來實作:
1 :host ::ng-deep h2 { 2 color: red; 3 }
運行時生成如下樣式:
1 <style> 2 [_nghost-c0] h2 { 3 color: red; 4 } 5 </style>
此樣式將應用于app-root內所有h2元素,
這種選擇器的組合很有用,當將樣式應用到使用ng-content傳遞給模板的元素,
:host-context
根據宿主元素的祖先元素的某些條件,將樣式應用于組件模板中的元素,這時:host-context會很有用,
注:只有宿主元素及其后代會受到樣式影響,而不是祖先元素,
1 @Component({ 2 selector: 'themeable-button', 3 template: ` 4 <button >Themeable Button</button> 5 `, 6 styles: [` 7 :host-context(.red-theme) .btn-theme { 8 background: red; 9 } 10 :host-context(.blue-theme) .btn-theme { 11 background: blue; 12 } 13 `] 14 }) 15 export class ThemeableButtonComponent { 16 17 }
現在的樣式是不起作用的;為了使樣式生效,需要向該組件的任何父元素添加一個主題激活類,
1 <div class="blue-theme"> 2 <themeable-button></themeable-button> 3 </div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/538569.html
標籤:其他
上一篇:07#Web 實戰:實作 GitHub 個人主頁專案拖拽排序
下一篇:本地JS檔案批量壓縮
