Angular 4 ViewEncapsulation

作者: semlinker | 来源:发表于2017-06-04 13:17 被阅读449次

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

    Web Components

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

    Web Components 是解决这类问题最好的良药,它通过一种标准化的非侵入的方式封装一个组件,每个组件能组织好它自身的 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>
    

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

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

    运行后的结果:

    angular-view-encapsulation-none.png

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

    运行后的结果:

    angular-view-encapsulation-emulated.png

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

    运行后的结果:

    angular-view-encapsulation-native.png

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

    参考资料

    相关文章

      网友评论

        本文标题:Angular 4 ViewEncapsulation

        本文链接:https://www.haomeiwen.com/subject/rhvvfxtx.html