angularJS2组件样式

把样式加载进组件中javascript

咱们有几种方式来把样式加入组件:css

内联在模板的 HTML 中

设置styles或styleUrls元数据html

经过 CSS 文件导入

上述做用域规则对全部这些加载模式都适用。
元数据中的样式java

咱们能够给@Component装饰器添加一个styles数组型属性。 这个数组中的每个字符串(一般也只有一个)定义一份 CSS。web

@Component({
      selector: 'hero-app',
      template: ` <h1>Tour of Heroes</h1> <hero-app-main [hero]=hero></hero-app-main>`,
      styles: ['h1 { font-weight: normal; }']
    })
    export class HeroAppComponent {
    /* . . . */
    }

模板内联样式
咱们也能够把它们放到express

@Component({
      selector: 'hero-controls',
      template: `
        <style> button { background-color: white; border: 1px solid #777; } </style>
        <h3>Controls</h3>
        <button (click)="activate()">Activate</button>
      `
    })

元数据中的样式表 URL数组

咱们还能够经过给组件的@Component装饰器中添加一个styleUrls属性来从外部 CSS 文件中加载样式:浏览器

 @Component({ selector: 'hero-details', template: ` <h2>{{hero.name}}</h2> <hero-team [hero]=hero></hero-team> <ng-content></ng-content> `, styleUrls: ['app/hero-details.component.css'] }) export class HeroDetailsComponent { /* . . . */ }

URL是相对于应用程序根目录的,它一般是应用的宿主页面index.html所在的地方。 这个样式文件的 URL 不是相对于组件文件的。这就是为何范例中的 URL 用app/开头。 参见附录 2 来了解如何指定相对于组件文件的 URL。app

像 Webpack 这类模块打包器的用户可能会使用styles属性来在构建时从外部文件中加载样式。它们可能这样写:svg

styles: [require(‘my.component.css’)]

注意,这时候咱们是在设置styles属性,而不是styleUrls属性! 是模块打包器在加载 CSS 字符串,而不是 Angular。 Angular 看到的只是打包器加载它们以后的 CSS 字符串。 对 Angular 来讲,这跟咱们手写了styles数组没有任何区别。 要了解这种 CSS 加载方式的更多信息,请参阅相应模块打包器的文档。
模板中的 link 标签

咱们也能够在组件的 HTML 模板中嵌入标签。

像styleUrls标签同样,这个 link 标签的href指向的 URL 也是相对于应用的根目录的,而不是组件文件。

 @Component({ selector: 'hero-team', template: ` <link rel="stylesheet" href="app/hero-team.component.css"> <h3>Team</h3> <ul> <li *ngFor="let member of hero.team"> {{member}} </li> </ul>` })

CSS @imports

咱们还能够利用标准的 CSS @import规则来把其它 CSS 文件导入到咱们的 CSS 文件中。

在这种状况下,URL 是相对于咱们执行导入操做的 CSS 文件的。

app/hero-details.component.css (excerpt)
@import 'hero-details-box.css';

控制视图的封装模式:原生 (Native)、仿真 (Emulated) 和无 (None)

像上面讨论过的同样,组件的 CSS 样式被封装进了本身的视图中,而不会影响到应用程序的其它部分。

经过在组件的元数据上设置视图封装模式,咱们能够分别控制每一个组件的封装模式。 可选的封装模式一共有三种:

Native模式使用浏览器原生的 Shadow DOM 实现来为组件的宿主元素附加一个 Shadow DOM。组件的样式被包裹在这个 Shadow DOM 中。(译注:不进不出,没有样式能进来,组件样式出不去。)

Emulated模式(默认值)经过预处理(并更名)CSS 代码来模拟 Shadow DOM 的行为,以达到把 CSS 样式局限在组件视图中的目的。 更多信息,见附录 1 。(译注:只进不出,全局样式能进来,组件样式出不去)

None意味着 Angular 不使用视图封装。 Angular 会把 CSS 添加到全局样式中。而不会应用上前面讨论过的那些做用域规则、隔离和保护等。 从本质上来讲,这跟把组件的样式直接放进 HTML 是同样的。(译注:能进能出。)

经过组件元数据中的encapsulation属性来设置组件封装模式:

// warning: few browsers support shadow DOM encapsulation at this time
encapsulation: ViewEncapsulation.Native

原生(Native)模式只适用于有原生 Shadow DOM 支持的浏览器。 所以仍然受到不少限制,这就是为何咱们会把仿真 (Emulated) 模式做为默认选项,并建议将其用于大多数状况。
附录 1:查看仿真 (Emulated) 模式下生成的 CSS

当使用默认的仿真模式时,Angular 会对组件的全部样式进行预处理,让它们模仿出标准的 Shadow CSS 做用域规则。

当咱们查看启用了仿真模式的 Angular 应用时,咱们看到每一个 DOM 元素都被加上了一些额外的

<hero-details _nghost-pmm-5>
  <h2 _ngcontent-pmm-5>Mister Fantastic</h2>
  <hero-team _ngcontent-pmm-5 _nghost-pmm-6>
    <h3 _ngcontent-pmm-6>Team</h3>
  </hero-team>
</hero-detail>

到了两种被生成的属性:

一个元素在原生封装方式下多是 Shadow DOM 的宿主,在这里被自动添加上一个_nghost属性。 这是组件宿主元素的典型状况。

组件视图中的每个元素,都有一个_ngcontent属性,它会标记出该元素是哪一个宿主的模拟 Shadow DOM。

这些属性的具体值并不重要。它们是自动生成的,而且咱们永远不会在程序代码中直接引用到它们。 但它们会做为生成的组件样式的目标,就像咱们在 DOM 的区所看到的:

[_nghost-pmm-5] { display: block; border: 1px solid black; }

h3[_ngcontent-pmm-6] { background-color: white; border: 1px solid #777; }

这些就是咱们写的那些样式被处理后的结果,因而每一个选择器都被增长了_nghost或_ngcontent属性选择器。 在这些附加选择器的帮助下,咱们实现了本指南中所描述的这些做用域规则。

小伙伴们会很愉快的使用仿真模式 —— 直到有一天 Shadow DOM 得到全面支持。
附录 2:使用相对 URL 加载样式

把组件的代码 (ts/js)、HTML 和 CSS 分别放到同一个目录下的三个不一样文件,是一个经常使用的实践:

quest-summary.component.ts
quest-summary.component.html
quest-summary.component.css

咱们会经过设置元数据的templateUrl和styleUrls属性把模板和 CSS 文件包含进来。 既然这些文件都与组件(代码)文件放在一块儿,那么经过名字,而不是到应用程序根目录的全路径来指定它,就会是一个漂亮的方式。

经过把组件元数据的moduleId属性设置为module.id,咱们能够更改 Angular 计算完整 URL 的方式
app/quest-summary.component.ts

@Component({
      moduleId: module.id,
      selector: 'quest-summary',
      templateUrl: 'quest-summary.component.html',
      styleUrls:  ['quest-summary.component.css']
    })
    export class QuestSummaryComponent { }