在介紹 Angular 2 ViewEncapsulation 以前,咱們先來介紹一下 Web Components 標準。css
近年來,web 開發者們經過插件或者模塊的形式在網上分享本身的代碼,便於其餘開發者們複用這些優秀的代碼。一樣的故事不斷髮生,人們不斷的複用 JavaScript 文件,而後是 CSS 文件,固然還有 HTML 片斷。可是你又必須祈禱這些引入的代碼不會影響到你的網站或者web app。html
WebComponents 是解決這類問題最好的良藥,它經過一種標準化的非侵入的方式封裝一個組件,每一個組件能組織好它自身的 HTML 結構、CSS 樣式、JavaScript 代碼,而且不會干擾頁面上的其餘元素。 web
Web Components 由如下四種技術組成:瀏覽器
Custom Elements - 自定義元素app
HTML Templates - HTML模板網站
Shadow DOM - 影子DOMspa
HTML Imports - HTML導入插件
由於 Shadow DOM 與 Angular ViewEncapsulation 相關, 因此這篇文章咱們主要介紹 Shadow DOM 相關的內容。code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Shadow DOM</title> <style type="text/css"> .shadowroot_son { color: #f00; } </style> </head> <body> <p class="shadowroot_son">我不在 Shadow Host內</p> <div class="shadowhost">Hello, world!</div> <script> // 影子宿主(shadow host) var shadowHost = document.querySelector('.shadowhost'); // 建立影子根(shadow root) var shadowRoot = shadowHost.createShadowRoot(); // 影子根做爲影子樹的第一個節點,其餘的節點好比p節點都是它的子節點。 shadowRoot.innerHTML = '<p class="shadowroot_son">我在 Shadow Host內</p>'; </script> </body> <html>
以上代碼成功運行後,以下圖:htm
咱們發如今 #shadow-root 中的元素,不受咱們外界定義的 CSS shadowroot_son 類影響。所以咱們能夠利用 Shadow DOM 來封裝咱們自定義的 HTML 標籤、CSS 樣式和 JavaScript 代碼。須要注意的是 Shadow DOM 兼容性還不是很好,具體請參考 - Can I Use Shadow DOM 。
接下來咱們開始介紹 Angular ViewEncapsulation Modes:
ViewEncapsulation 容許設置三個可選的值:
ViewEncapsulation.Emulated - 無 Shadow DOM,可是經過 Angular 提供的樣式包裝機制來封裝組件,使得組件的樣式不受外部影響。這是 Angular 的默認設置。
ViewEncapsulation.Native - 使用原生的 Shadow DOM 特性
ViewEncapsulation.None - 無 Shadow DOM,而且也無樣式包裝
ViewEncapsulation 枚舉定義:
export enum ViewEncapsulation { Emulated, // 默認值 Native, None }
ViewEncapsulation.None
import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h4>Welcome to Angular World</h4> <p class="greet">Hello {{name}}</p> `, styles: [` .greet { background: #369; color: white; } `], encapsulation: ViewEncapsulation.None // None | Emulated | Native }) export class AppComponent { name: string = 'Semlinker'; }
運行後的結果:
ViewEncapsulation.None 設置的結果是沒有 Shadow DOM,而且全部的樣式都應用到整個 document,換句話說,組件的樣式會受外界影響,可能被覆蓋掉。
ViewEncapsulation.Emulated
import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'my-app', ..., encapsulation: ViewEncapsulation.Emulated // None | Emulated | Native }) export class AppComponent { name: string = 'Semlinker'; }
運行後的結果:
ViewEncapsulation.Emulated 設置的結果是沒有 Shadow DOM,可是經過 Angular 提供的樣式包裝機制來封裝組件,使得組件的樣式不受外部影響。雖然樣式仍然是應用到整個 document,但 Angular 爲 .greet 類建立了一個 [_ngcontent-cmy-0] 選擇器。能夠看出,咱們爲組件定義的樣式,被 Angular 修改了。其中的 _nghost-cmy- 和 _ngcontent-cmy- 用來實現局部的樣式。
ViewEncapsulation.Native
import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'my-app', ..., encapsulation: ViewEncapsulation.Native // None | Emulated | Native }) export class AppComponent { name: string = 'Semlinker'; }
運行後的結果:
ViewEncapsulation.Native 設置的結果是使用原生的 Shadow DOM 特性。Angular 會把組件按照瀏覽器支持的 Shadow DOM 形式渲染,渲染結果如上圖所示。
在瞭解 Angular 2 ViewEncapsulation(視圖包裝) 特性前,咱們先介紹了 WebComponents 標準及標準中的 Shadow DOM 技術。後面咱們經過實際的示例,展現了 ViewEncapsulation 支持的三種模式,並總結了各個模式的特色。後面咱們還會有專門的文章介紹 Angular 2 中樣式的應用方案。