ViewEncapsulation.Native,ViewEncapsulation.None和ViewEncapsulation.Emulated

时间:2016-02-26 12:39:40

标签: typescript angular

有人可以解释 ViewEncapsulation.Native, ViewEncapsulation.None ViewEncapsulation.Emulated 之间的区别> angular2

我试图谷歌并阅读一些文章,但我无法理解其中的差异。

下面我有两个组件Home(home.ts),即父组件和MyComp(my-comp.ts)。我想在父组件中定义正在子组件中使用的样式。

我应该使用 ViewEncapsulation.Native 还是 ViewEncapsulation.None

home.ts

import {Component, ViewEncapsulation} from 'angular2/core';
import {MyComp} from './my-comp';
@Component({
  selector: 'home',  // <home></home>
  providers: [
  ],
  directives: [
    MyComp
  ],
  styles: [`
    .parent-comp-width {
       height: 300px;
       width: 300px;
       border: 1px solid black;
     }
    `],
  template:`
    <my-comp></my-comp>
    <div class="parent-comp-width"></div>
  `,
  encapsulation: ViewEncapsulation.Native
})
export class Home {
}

MY-comp.ts

import {Component} from 'angular2/core';

@Component({
  selector: 'my-comp',  // <home></home>
  template: `
  <div class="parent-comp-width">my-comp</div>
  `
})
export class MyComp {
}

6 个答案:

答案 0 :(得分:20)

<强>更新 如果您希望将Parent添加到Child的样式应用于ViewEncapsulation.None,则需要在Child组件中设置Emulated,以防止样式出血。

NativeNone只是阻止样式进出组件的两种不同方法。 ViewEncapsulation.Emulated是唯一允许样式跨越组件边界的方法。

<强>原始

  • ViewEncapsulation.None很简单,没有封装

  • ViewEncapsulation.Emulated(目前是Angular2中的默认值)
    将属性添加到组件标签和子元素,并操纵添加到页面的CSS(将属性添加到选择器),以便样式不会相互渗透 - 将样式作为范围保存到添加它们的组件,即使样式在加载组件时,都会在页面的头部收集所有内容。

  • ViewEncapsulation.Native使用shadow DOM创建自定义元素,其中浏览器本机实现确保样式范围。
    如果浏览器本身不支持shadow DOM,则需要Web组件polyfill来填充行为。这类似于Emulated,但是polyfill更昂贵,因为它们填充了大量的浏览器API,即使它们中的大多数从未使用过。 Angulars <div id="Insert_here">Name <div id="Image">Name //Or whatever you call it. 仿真只会增加它使用的成本,因此对Angular应用程序来说效率更高。

答案 1 :(得分:2)

  • 本地:使用浏览器的本地Shadow DOM。启用浏览器之前,请先检查浏览器支持。
  • ShadowDom::使用浏览器的本机Shadow DOM v1获得更好的跨浏览器支持,并且是所有浏览器的共享标准。检查Shadow DOM v0与v1之间的区别。
  • 仿真的:模仿Shadow DOM的行为来确定组件的CSS范围并追加到头部。
  • :Shadow DOM和自定义实现都没有,例如全局CSS会附加到头部
  

Angular使用ViewEncapsulation。模拟为默认封装模式。

答案 2 :(得分:0)

如果有人因为想要通过父组件样式声明来设置子组件的样式而遇到这个问题,请参阅this SO answer

但是,正如对接受的答案的最新评论所示,Angular docs说:

  

阴影穿透后代组合子已被弃用且支持   从主要浏览器和工具中删除。因此我们打算放弃   支持Angular(对于所有3个/ deep /,&gt;&gt;&gt;和:: ng-deep)。直到   那么:: ng-deep应该是首选,以实现更广泛的兼容性   工具。

答案 3 :(得分:0)

from pro-angular book:

ViewEncapsulation值:

  • 模拟:指定此值后,Angular会通过编写内容和样式以添加属性来模拟Shadow DOM。如果未指定封装值,这是默认行为。

    如果使用浏览器的F12开发人员工具检查DOM,您将看到外部CSS文件的内容。

    ...
    <style>
    div[_ngcontent-c0] {
      background-color: lightcoral;
    }
    </style>
    ...

修改了选择器,使其与div元素匹配 名为_ngcontent-c0的属性,尽管您可能会在 属性名称是由Angular动态生成的。

为了确保style元素中的CSS仅影响由组件管理的HTML元素,请修改模板中的元素,使其具有相同的动态生成的属性,如下所示:

...
<div _ngcontent-c0="" class="form-group">
   <label _ngcontent-c0="">Name</label>
   <input _ngcontent-c0="" class="form-control ng-untouched ng-pristineng-invalid" 
        ng-reflect-name="name" name="name">
</div>
...
  • 本地:指定此值后,Angular将使用浏览器的影子DOM功能。仅在浏览器实现影子DOM或使用polyfill时,此方法才有效。
  • :指定此值后,Angular会简单地将未修改的CSS样式添加到HTML文档的开头部分,并让浏览器找出如何使用常规CSS优先规则来应用样式。

“ Native”和“ None”值应谨慎使用。浏览器对影子DOM功能的支持非常有限,以至于仅当您使用提供与其他浏览器兼容的polyfill库时,才可以使用Native选项。

“无”选项将组件定义的所有样式添加到HTML文档的开头部分,并使浏览器确定如何应用它们。这样做的好处是可以在所有浏览器中使用,但是结果是不可预测的,并且不同组件定义的样式之间没有隔离。

答案 4 :(得分:0)

请参考以下示例以了解所有三个选项:

encapsulation: ViewEncapsulation.Emulated
encapsulation: ViewEncapsulation.Native
encapsulation: ViewEncapsulation.None

Click here看例子

答案 5 :(得分:0)

让我们以ComponentParent包含ComponentChild的情况为例。对于此示例,我们将讨论ComponentParent的不同封装方案。

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

@Component({
  selector: 'component-child',
  // templateUrl: './child.component.html',
  template: '<h1>Hello, child</h1>',
  // styleUrls: ['./child.component.scss'],
  style: '/* ... */'
})
export class ComponentParent {
  // ...
}

@Component({
  selector: 'component-parent',
  template: '<h1>Hello, parent</h1><component-child/>',
  style: 'h1{background-color:yellow}',
  encapsulation: ViewEncapsulation.Emulated // this is the default encapsulation for the angular component
})
export class ComponentParent {
  // ...
}

ViewEncapsulation具有1个废弃的值:

和3个有效值:

这是透明模式,最类似于根本不涉及角度的情况。

ComponentParentComponentChild都将带有黄色背景的H1标签。

ShadowDom

此模式在组件(在我们的示例中为ComponentParent)内容周围创建 本地阴影DOM 根。这将保护我们在组件内部声明的任何(CSS / SASS)样式,以泄漏到组件外部。但是,它将应用于诸如ComponentChild之类的子组件。

ComponentParentComponentChild都将带有带有黄色背景的H1标签(类似于None模式),但是ComponentParent之外的任何H1标签都不会受到影响。

模拟

简而言之,这仅将ComponentParent中声明的样式应用于ComponentParent内容,但排除子组件,例如ComponentChild。换句话说,仅在“ ” HTML元素上,而不在有角网(组件)元素上。

只有ComponentParent的H1标签带有黄色背景。

关于仿真机制的其他说明

Emulated模式通常对我们来说是透明的,因为我们倾向于放置将同时渗透ComponentParent和{的全局样式(影响ComponentChildNone)。 {1}}组件及其子组件和HTML元素。

但是,假设Emulated是第3方组件,并且您想为其设置样式。如果在ComponentChild组件上应用Emulated模式,则将无法执行此操作。这是由于ComponentParent实现:

Emulated组件内的

每个HTML元素将使用component-name属性(无值)修饰,例如:

  • ComponentParent :用于组件容器
  • _nghost-c3 :获取组件的内容

我们的组件_ngcontent-c3中的并行每个(S)CSS选择器将被“封装”(带有条件),具有相同的组件名称属性

ComponentParent

总体而言,这意味着仅.H1[_ngcontent-c3] { background-color:yellow; } 的元素会受到影响,而我们装饰第三方组件的H1的目标将失败,因为它没有(相同,如果有的话)组件-name属性(ComponentParent

第三方组件的解决方案

  • 使用_ngcontent-c3(如果可用)
  • 禁用封装,使用ShadowDom
  • 在全局(S)CSS中放置样式
  • 通过使用component-name属性装饰其内部元素来模拟内部第三方组件