在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