Angular 2 ViewEncapsulation

在介紹 Angular 2 ViewEncapsulation 以前,咱們先來介紹一下 Web Components 標準。css

Web Components

近年來,web 開發者們經過插件或者模塊的形式在網上分享本身的代碼,便於其餘開發者們複用這些優秀的代碼。一樣的故事不斷髮生,人們不斷的複用 JavaScript 文件,而後是 CSS 文件,固然還有 HTML 片斷。可是你又必須祈禱這些引入的代碼不會影響到你的網站或者web app。html

WebComponents 是解決這類問題最好的良藥,它經過一種標準化的非侵入的方式封裝一個組件,每一個組件能組織好它自身的 HTML 結構、CSS 樣式、JavaScript 代碼,而且不會干擾頁面上的其餘元素。 web

Web Components 由如下四種技術組成:瀏覽器

由於 Shadow DOM 與 Angular ViewEncapsulation 相關, 因此這篇文章咱們主要介紹 Shadow DOM 相關的內容。code

Shadow DOM

<!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 容許設置三個可選的值:

  • 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 中樣式的應用方案。

參考資料

相關文章
相關標籤/搜索