Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 2 ViewEncapsulation #17

Open
semlinker opened this issue Mar 13, 2017 · 0 comments
Open

Angular 2 ViewEncapsulation #17

semlinker opened this issue Mar 13, 2017 · 0 comments

Comments

@semlinker
Copy link
Owner

在介绍 Angular 2 ViewEncapsulation 之前,我们先来介绍一下 Web Components 标准。

Web Components

近年来,web 开发者们通过插件或者模块的形式在网上分享自己的代码,便于其他开发者们复用这些优秀的代码。同样的故事不断发生,人们不断的复用 JavaScript 文件,然后是 CSS 文件,当然还有 HTML 片段。但是你又必须祈祷这些引入的代码不会影响到你的网站或者web app。

WebComponents 是解决这类问题最好的良药,它通过一种标准化的非侵入的方式封装一个组件,每个组件能组织好它自身的 HTML 结构、CSS 样式、JavaScript 代码,并且不会干扰页面上的其他元素。

Web Components 由以下四种技术组成:

因为 Shadow DOM 与 Angular ViewEncapsulation 相关, 所以这篇文章我们主要介绍 Shadow DOM 相关的内容。

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>

以上代码成功运行后,如下图:

angular2-view-encapsulation

我们发现在 #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';
}

运行后的结果:

angular2-view-encapsulation-none

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';
}

运行后的结果:

angular2-view-encapsulation-emulated

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';
}

运行后的结果:

angular2-view-encapsulation-native

ViewEncapsulation.Emulated 设置的结果是使用原生的 Shadow DOM 特性。Angular 会把组件按照浏览器支持的 Shadow DOM 形式渲染,渲染结果如上图所示。

总结

在了解 Angular 2 ViewEncapsulation(视图包装) 特性前,我们先介绍了 WebComponents 标准及标准中的 Shadow DOM 技术。后面我们通过实际的示例,展示了 ViewEncapsulation 支持的三种模式,并总结了各个模式的特点。后面我们还会有专门的文章介绍 Angular 2 中样式的应用方案。

参考资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant