ViewEncapsulation.Native,ViewEncapsulation.None和ViewEncapsulation.Emulated之间的差异

Par*_*mod 31 typescript angular

有人可以解释ViewEncapsulation.Native, ViewEncapsulation.NoneViewEncapsulation.Emulated in 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 {
}
Run Code Online (Sandbox Code Playgroud)

我-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 {
}
Run Code Online (Sandbox Code Playgroud)

Gün*_*uer 25

更新 如果您希望添加到Parent应用程序的样式Child需要ViewEncapsulation.NoneChild组件中设置,以便它不会阻止样式流失.

Emulated并且Native只是两种不同的方法来防止样式流入和流出组件.None是唯一允许样式跨越组件边界的方法.

原版的

  • ViewEncapsulation.None很简单没有封装

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

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


mPr*_*inC 8

ComponentParent让我们以contains的场景为例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 {
  // ...
}

Run Code Online (Sandbox Code Playgroud)

ViewEncapsulation 有 1 个废弃值:

和 3 个有效值:

没有任何

这是透明模式,与完全不涉及角度的场景最相似。

ComponentParent都会ComponentChild有黄色背景的 H1 标签。

影子王国

此模式在组件(在我们的例子中:)内容周围创建一个原生影子 DOMComponentParent根。这将保护我们在组件内部声明的任何(CSS/SASS)样式泄漏到组件外部。但是,它将适用于子组件,例如ComponentChild.

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

模拟

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

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

对仿真机制的补充说明

Emulated模式通常对我们来说是透明的,因为我们更喜欢放置全局样式(影响 和ComponentParentComponentChild,它将渗透NoneEmulated组件及其子组件和 HTML 元素。

然而,假设这ComponentChild是一个第三方组件,并且您想要对其进行样式设置。您将无法使用组件Emulated上应用的模式来执行此操作ComponentParent。这是由于Emulated实施:

组件内的每个 HTML 元素ComponentParent都将使用组件名称属性(无值)进行装饰,例如:

  • _nghost-c3:用于组件容器
  • _ngcontent-c3: 为组件的内容

并行地,我们组件中的每个 (S)CSS 选择器ComponentParent都将使用相同的组件名称属性“封装”(条件化)

.H1[_ngcontent-c3] {
  background-color:yellow;
}
Run Code Online (Sandbox Code Playgroud)

总的来说,这意味着只有 的元素ComponentParent会受到影响,并且我们装饰第 3 方组件 H1 的目标将会失败,因为它没有(相同,如果有的话)组件名称属性 ( _ngcontent-c3)

第三方组件的解决方案

  • ShadowDom如果可用的话使用
  • 禁用封装,使用None
  • 将样式放入全局 (S)CSS
  • 通过使用组件名称属性装饰其元素来模拟内部第 3 方组件的仿真


Har*_*hva 7

  • Native:使用浏览器的原生 Shadow DOM。在启用之前检查浏览器支持。
  • ShadowDom:使用浏览器的原生 Shadow DOM v1 以获得更好的跨浏览器支持,并且是跨浏览器的共享标准。检查 Shadow DOM v0 到 v1 之间的差异。
  • 模拟:模仿 Shadow DOM 的行为来限定组件的 CSS 范围并附加到头部。
  • 无: Shadow DOM 和自定义实现都没有,比如附加到头部的全局 CSS

Angular 使用 ViewEncapsulation.Emulated 作为默认封装模式。