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

相关文章
相关标签/搜索