ViewEncapsulation簡介

2018-06-06 08:57 更新

在介紹 ViewEncapsulation 之前,我們先來介紹一下 Web Components 標(biāo)準(zhǔn)。

Web Components

近年來,Web 開發(fā)者們通過插件或者模塊的形式在網(wǎng)上分享自己的代碼,便于其他開發(fā)者們復(fù)用這些優(yōu)秀的代碼。同樣的故事不斷發(fā)生,人們不斷的復(fù)用 JavaScript 文件,然后是 CSS 文件,當(dāng)然還有 HTML 片段。但是你又必須祈禱這些引入的代碼不會影響到你的網(wǎng)站或者 Web App。

Web Components 是解決這類問題最好的良藥,它通過一種標(biāo)準(zhǔn)化的非侵入的方式封裝一個(gè)組件,每個(gè)組件能組織好它自身的 HTML 結(jié)構(gòu)、CSS 樣式、JavaScript 代碼,并且不會干擾頁面上的其他元素。

Web Components 由以下四種技術(shù)組成:

因?yàn)?Shadow DOM 與 Angular ViewEncapsulation 相關(guān), 所以這篇文章我們主要介紹 Shadow DOM 相關(guān)的內(nèi)容。

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內(nèi)</p>
<div class="shadowhost">Hello, world!</div>
<script>
    // 影子宿主(shadow host)
    var shadowHost = document.querySelector('.shadowhost');
    // 創(chuàng)建影子根(shadow root)
    var shadowRoot = shadowHost.createShadowRoot();
    // 影子根作為影子樹的第一個(gè)節(jié)點(diǎn),其他的節(jié)點(diǎn)比如p節(jié)點(diǎn)都是它的子節(jié)點(diǎn)。
    shadowRoot.innerHTML = '<p class="shadowroot_son">我在 Shadow Host內(nèi)</p>';
</script>
</body>
<html>

以上代碼成功運(yùn)行后,如下圖:

angular-view-encapsulation

我們發(fā)現(xiàn)在 #shadow-root 中的元素,不受我們外界定義的 CSS shadowroot_son 類影響。因此我們可以利用 Shadow DOM 來封裝我們自定義的 HTML 標(biāo)簽、CSS 樣式和 JavaScript 代碼。需要注意的是 Shadow DOM 兼容性還不是很好,具體請參考 - Can I Use Shadow DOM 。

接下來我們開始介紹 Angular ViewEncapsulation Modes:

ViewEncapsulation

ViewEncapsulation 允許設(shè)置三個(gè)可選的值:

  • ViewEncapsulation.Emulated - 無 Shadow DOM,但是通過 Angular 提供的樣式包裝機(jī)制來封裝組件,使得組件的樣式不受外部影響。這是 Angular 的默認(rèn)設(shè)置。
  • ViewEncapsulation.Native - 使用原生的 Shadow DOM 特性
  • ViewEncapsulation.None - 無 Shadow DOM,并且也無樣式包裝

ViewEncapsulation 枚舉定義:

export enum ViewEncapsulation {
  Emulated, // 默認(rèn)值
  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';
}

運(yùn)行后的結(jié)果:

angular-view-encapsulation-none.png

ViewEncapsulation.None 設(shè)置的結(jié)果是沒有 Shadow DOM,并且所有的樣式都應(yīng)用到整個(gè) 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';
}

運(yùn)行后的結(jié)果:

angular-view-encapsulation-emulated.png

ViewEncapsulation.Emulated 設(shè)置的結(jié)果是沒有 Shadow DOM,但是通過 Angular 提供的樣式包裝機(jī)制來封裝組件,使得組件的樣式不受外部影響。雖然樣式仍然是應(yīng)用到整個(gè) document,但 Angular 為 .greet 類創(chuàng)建了一個(gè) [_ngcontent-cmy-0] 選擇器??梢钥闯?,我們?yōu)榻M件定義的樣式,被 Angular 修改了。其中的 _nghost-cmy-*_ngcontent-cmy-* 用來實(shí)現(xiàn)局部的樣式。

ViewEncapsulation.Native

import { Component, ViewEncapsulation } from '@angular/core';


@Component({
  selector: 'my-app',
  ...,
  encapsulation: ViewEncapsulation.Native // None | Emulated | Native
})
export class AppComponent {
  name: string = 'Semlinker';
}

運(yùn)行后的結(jié)果:

angular-view-encapsulation-native.png

ViewEncapsulation.Native 設(shè)置的結(jié)果是使用原生的 Shadow DOM 特性。Angular 會把組件按照瀏覽器支持的 Shadow DOM 形式渲染,渲染結(jié)果如上圖所示。

參考資料

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號