AngularDart4.0 高級-組件樣式

Angular應用程序使用標準CSS進行樣式化。 這意味着您能夠將全部關於CSS樣式表,選擇器,規則和媒體查詢的知識直接應用於Angular應用程序。css

此外,Angular能夠將組件樣式與組件捆綁在一塊兒,從而實現比常規樣式表更多的模塊化設計。html

本頁介紹如何加載和應用這些組件樣式。java

運行此頁面中顯示的代碼的實例(查看源代碼)。git

使用組件樣式

對於您編寫的每一個Angular組件,您不只能夠定義HTML模板,還能夠定義與該模板一塊兒使用的CSS樣式,指定您須要的任何選擇器,規則和媒體查詢。github

一種方法是在組件元數據中設置styles屬性。 styles屬性採用包含CSS代碼的字符串列表。 一般你給它一個字符串,以下例所示:lib/app_component.dartweb

@Component(
    selector: 'hero-app',
    template: '''
      <h1>Tour of Heroes</h1>
      <hero-app-main [hero]="hero"></hero-app-main>''',
    styles: const ['h1 { font-weight: normal; }'],
    directives: const [HeroAppMainComponent])
class AppComponent {
// ···
}

您放入組件樣式中的選擇器僅適用於該組件中的模板。 上例中的h1選擇器僅適用於HeroAppComponent模板中的<h1>標記。 應用中其餘地方的任何<h1>元素都不受影響。瀏覽器

與傳統的CSS工做方式相比,這是模塊化方面的重大改進。app

  • 您能夠在每一個組件的上下文中使用最有意義的CSS類名稱和選擇器。
  • 類名和選擇器是組件本地的,不會與應用程序中其餘地方使用的類和選擇器相沖突。
  • 應用程序中其餘位置的樣式更改不會影響組件的樣式。
  • 您能夠將每一個組件的CSS代碼與組件的Dart和HTML代碼共同定位,從而生成整潔的項目結構。
  • 您能夠更改或刪除組件CSS代碼,而無需搜索整個應用程序以查找代碼的使用位置。

特殊選擇器

組件樣式有一些取於DOM樣式範圍中的特殊選擇器(在W3C站點的CSS範圍模塊1級頁面中描述)。dom

:host

使用:host僞類選擇器來定位承載組件的元素中的樣式(而不是定位組件模板中的元素)。ide

lib/src/hero_details_component.css (host)

:host {
  display: block;
  border: 1px solid black;
}

:host選擇器是定位宿主元素的惟一方法。您不能使用其餘選擇器從組件內部到達宿主元素,由於它不是組件本身的模板的一部分。宿主元素位於父組件的模板中。

經過在:host以後的括號中包含另外一個選擇器使用函數形式有條件地應用宿主樣式

下一個示例再次定位主機元素,但僅限於它還具備activeCSS類。

lib/src/hero_details_component.css (host function)

:host(.active) {
  border-width: 3px;
}

:host-context

有時候,根據組件視圖以外的某些條件來應用樣式會頗有用。例如,一個CSS主題類能夠應用於文檔<body>元素,而且你想改變你的組件看起來如何基於這個。

使用:host-context()僞類選擇器,它的做用就像:host()的函數形式同樣。:host-context()選擇器在組件宿主元素的任意祖先中查找CSS類,直到文檔根。當與另外一個選擇器組合時,:host-contex()選擇器頗有用。

如下示例僅在某個祖先元素具備CSS類theme-light的狀況下,纔會將background-color樣式應用於組件內的全部<h2>元素。

lib/src/hero_details_component.css (host-context)

:host-context(.theme-light) h2 {
  background-color: #eef;
}

::ng-deep

組件樣式一般僅適用於組件本身的模板中的HTML。

使用::ng-deep選擇器能夠經過子組件樹強制一個樣式到全部的子組件視圖。::ng-deep選擇器適用於嵌套組件的任何深度,而且適用於組件的視圖子組件和內容子組件。

如下示例將全部<h3>元素做爲目標,從宿主元素向下到這個組件到它的全部子元素。

lib/src/hero_details_component.css (deep)

:host ::ng-deep h3 {
  font-style: italic;
}

僅在模擬視圖封裝中使用::ng-deep選擇器.模擬是默認和最經常使用的視圖封裝。有關更多信息,請參閱控制視圖封裝部分。

加載樣式到組件

這裏有幾種加載樣式到組件的方法:

  • 經過設置stylesstyleUrls元數據.
  • HTML模板內鏈樣式.
  • CSS導入.

做用規則條例早期適用於每一個加載模式.

元數據中使用Styles

能夠添加一個styles列表屬性到@Component註解. 列表中的每個(一般只有一個字符串) 定義CSS. lib/app_component.dart

@Component(
    selector: 'hero-app',
    template: '''
      <h1>Tour of Heroes</h1>
      <hero-app-main [hero]="hero"></hero-app-main>''',
    styles: const ['h1 { font-weight: normal; }'],
    directives: const [HeroAppMainComponent])
class AppComponent {
// ···
}

元數據中使用Style URLs

能夠經過添加一個styleUrls屬性到組件的@Component 註解從外部CSS文件加載樣式:

lib/src/hero_details_component.dart (styleUrls)

@Component(
    selector: 'hero-details',
    template: '''
      <h2>{{hero.name}}</h2>
      <hero-team [hero]="hero"></hero-team>
      <ng-content></ng-content>''',
    styleUrls: const ['hero_details_component.css'],
    directives: const [HeroTeamComponent])
class HeroDetailsComponent {
  // ···
}

注意styleUrls中的URLs與組件是相對路徑.

模板內聯樣式

能夠枚舉樣式到HTML模板經過放置他們到<style>標籤內部.

lib/src/hero_controls_component.dart (inline styles)

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

  void activate() {
    hero.active = true;
  }
}

模板link標籤

你能夠枚舉<link>標籤到組件的HTML 模板.

<link>標籤的href URL相對於應用根路徑, 而不是組件文件.

lib/src/hero_team_component.dart (stylesheet link)

@Component(
  selector: 'hero-team',
  template: '''
      <link rel="stylesheet" href="hero_team_component.css">
      <h3>Team</h3>
      <ul>
        <li *ngFor="let member of hero.team">
          {{member}}
        </li>
      </ul>''',
  directives: const [CORE_DIRECTIVES],
)
class HeroTeamComponent {
  @Input()
  Hero hero;
}

CSS @imports

你可使用標準CSS @import規則導入CSS文件到CSS文件. 詳情, 在MDN站點查看@import

這個例子中的URL與CSS 文件是相對路徑.

lib/src/hero_details_component.css (excerpt)

@import 'hero_details_box.css';

封裝控制視圖:native,emulated,和none

如早期討論的同樣, 組件 CSS 樣式封裝到組件視圖 而且不影響應用程序的其它部分.
控制每一個組件底層之上封裝如何發生, 你能夠在組件元數據裏設置 視圖封裝模型. 從下列模式中選擇:

  • Native視圖封裝 使用了瀏覽器的原生shadow DOM實現 (查看Shadow DOMMDN站點上) 附加一個shadow DOM到組件的宿主元素上, 而且將組件視圖放入shadow DOM內. 組件的樣式包含在shadow DOM內.
  • Emulated視圖封裝 (默認) 仿真shadow DOM的行爲經過預處理 (和重命名)CSS代碼到有效的CSS到組件視圖. 更多信息, 查看附錄1.
  • None意味着Angular沒有視圖封裝. Angular添加CSS 到全局樣式. 做用域規則, 隔離, 和保護的早期論述不會被應用. 本質上與粘貼組件的樣式到HTML一致.

設置組件封裝模型,使用組件元數據中的encapsulation屬性:

lib/src/quest_summary_component.dart (native encapsulation)

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

Native視圖封裝僅僅在瀏覽器原生支持shadow DOM ( 在Can I use站點查看Shadow DOM v0)時有效. 支持仍然有限, 那就是爲何Emulated視圖封裝是默認的模型而且在大多數例子中被推薦.

附錄 1: 檢查在emulated視圖封裝模型產生的CSS

當使用emulated視圖封裝時, Angular預處理全部組件樣式以至接近標準shadow CSS 做用域規則.
使用emulated視圖封裝的處於運行狀態的Angular應用中的DOM, 每個DOM元素都有額外的類附加在上面:

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

這裏有兩種生成的類:

  • 一個元素將成爲shadow DOM 宿主在原生封裝中 生成的 _nghost 類. 這是組件宿主元素的通常實例.
  • 在組件視圖裏的元素有一個_ngcontent 類 用來標識這個元素屬於模仿哪個宿主的shadow DOM.

這些類的精確值是不重要的. 它們是自動生成的而且你未在應用代碼中涉及到. 但它們經過生成的組件樣式被定向,在DOM中的<head>區塊 :

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

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

這些樣式是後處理的以便每一個選擇器使用_nghost_ngcontent類選擇器來加強. 這些額外的選擇器使做用域規則能夠在此頁面描述.

附錄2: 使用相對路徑的URLs加載樣式

一般慣例是分割組件的代碼、CSS和HTML到同一目錄下的三個分離文件中:

  • quest_summary_component.dart
  • quest_summary_component.html
  • quest_summary_component.css

你能夠經過設置獨自的templateUrlstyleUrls元數據屬性來包含CSS和模板文件. 由於這些文件與組件本地協做, 經過名字引用它們是很是不錯的 除此而外也能夠指定一個路徑返回到應用的根.

感激的是, 這是在AngularDart相對定位URLs中默認解釋 :

templateUrl: 'quest_summary_component.html',
styleUrls: const ['quest_summary_component.css'])
相關文章
相關標籤/搜索