Angular 組件樣式的封裝(隔離)

Angular 組件樣式的封裝

樣式封裝

在html中,不管一個style元素定義在什麼地方,其內部的規則都是做用到整個html文檔的。
從框架的設計和使用者角度來看,對組件樣式都一種封裝需求:就是但願針對組件定義的樣式只在這個組件內部生效,不影響這個組件以外的元素。
Angular 提供了3種樣式封裝選項: ViewEncapsulation.Native, ViewEncapsulation.Emulated, ViewEncapsulation.None。 這裏有篇介紹文章:https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html
能夠在定義組件時配置樣式封裝的方式,例如:css

@Component({
  moduleId: module.id,
  selector: '...',
  templateUrl: '....component.html',
  styles: [`...`],
  encapsulation: ViewEncapsulation.None
})

默認的封裝方式是 ViewEncapsulation.Emulated, 由於Native會使用shadow Dom, 而shadow Dom 如今並無獲得普遍的瀏覽器支持。html

默認的樣式封裝帶來的問題

默認的封裝方式 Emulated ,Angular在運行時會同時對該組件的 html 模板和 css規則進行修改:web

  • html模板中的元素都會添加一個屬性 _ngcontent-c* , 星號表示一個數字,例如api

    <div _ngcontent-c39="" class="topo-container">
  • 每條樣式規則的每一個selector都會加上和上面元素新增的屬性對應的屬性選擇器,例如:瀏覽器

    你定義的規則是這樣的:angular2

    div.button-cotainer div.play-button button.fa-arrow-left {
        padding-left: 7px;
        padding-top: 1px;
    }

    在瀏覽器中查看規則,你看到的是這樣的:app

    div.button-cotainer[_ngcontent-c39]   div.play-button[_ngcontent-c39]   button.fa-arrow-left            [_ngcontent-c39] {
        padding-left: 7px;
        padding-top: 1px;
    }

    上面這種對CSS規則的修改,會帶來一個問題框架

  • 因爲在JS代碼中經過web api(例如 appenChild())動態添加的元素是沒有 _ngcontent-c* 這種屬性的,致使組件的元數據中的CSS規則沒法應用到這種動態添加的元素。dom

規避這個問題的方法:使用 /deep/ 語法,該語法告知angular不要在 /deep/以後的元素類型上添加屬性修飾,例如:選擇器 /deep/ p span 通過angular編譯後 就是 p span, 固然這樣就使得樣式具備了全局性,因此最好是結合:host 使用, 例如 :host /deep/ p span。spa

相關文章
相關標籤/搜索