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 中样式的应用方案。

参考资料