typescript ViewEncapsulation.Native、ViewEncapsulation.None和ViewEncapsulation.Emulated之间的差异

67up9zun  于 2023-02-25  发布在  TypeScript
关注(0)|答案(6)|浏览(126)

有人能解释一下视图封装.本机,****视图封装.无视图封装.在angular2中模拟之间的区别吗?
我试着在谷歌上搜索,读了一些文章,但我无法理解其中的区别。
下面我有两个组件Home(home.ts),即父组件和MyComp(my-comp.ts)。我想在父组件中定义子组件中使用的样式。
我应该使用视图封装.本机还是视图封装.无

  • 家.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 {
}
  • 我的公司ts*
import {Component} from 'angular2/core';

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

mrzz3bfm1#

    • update**如果要将添加到Parent的样式应用到Child,则需要在Parent组件中设置ViewEncapsulation.None,以便它不会阻止样式渗入。

EmulatedNative只是防止样式渗入组件和从组件渗出的两种不同方法。None是唯一允许样式跨越组件边界的方法。

    • 原件**
  • 视图封装。无简单无封装
  • ViewEncapsulation.Emulated(当前为Angular2中的默认值)

将属性添加到组件标签和子元素,并操作添加到页面的CSS(将属性添加到选择器),以使样式不会彼此渗透,从而使样式的作用域限于添加它们的组件,即使在加载组件时样式都是在页面的头部收集添加的。

  • ViewEncapsulation.Native创建带有shadow DOM的定制元素,浏览器的本地实现确保样式范围。

如果浏览器本身不支持shadow DOM,则需要web组件的polyfill来填充该行为。这类似于ViewEncapsulation.Emulated,但polyfill更昂贵,因为它们填充了大量的浏览器API,即使其中大部分从未使用过。Angular Emulated仿真只是增加了它所使用的成本,因此对于Angular应用程序来说效率要高得多。

7fhtutme

7fhtutme2#

***本机:**使用浏览器的本机Shadow DOM。请在启用之前检查浏览器支持。
***ShadowDom:**使用浏览器的本机Shadow DOM v1以获得更好的跨浏览器支持,它是跨浏览器的共享标准。请检查Shadow DOM v0与v1之间的差异。
***Emulated:**模仿Shadow DOM的行为,以确定组件的CSS范围并将其附加到head。
***无:**既不支持Shadow DOM,也不支持自定义实现,如附加到头部的全局CSS

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

os8fio9y

os8fio9y3#

让我们以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个废弃值:

*Native-使用过时的Shadow DOM v0

和3个有效值:

这是透明模式,与完全不涉及Angular 的场景最相似。
ComponentParentComponentChild都将具有黄色背景的H1标签。

暗影穹顶

此模式在组件周围创建***一个本地阴影DOM***根(在我们的示例中:ComponentParent)内容。这将保护我们在组件内部声明的任何(CSS/SASS)样式泄漏到组件外部。但是,它将应用于像ComponentChild这样的子组件。
ComponentParentComponentChild都将具有黄色背景的H1标签(类似于None模式),但ComponentParent之外的任何H1标签将不受影响。

模拟

简而言之,这将ComponentParent中声明的样式ONLY和ONLY应用于ComponentParent内容,但EXCLUDING子组件(如ComponentChild)。换句话说,仅应用于“pure”HTML元素,而不应用于Angular web(组件)元素。
只有ComponentParent将具有黄色背景的H1标签。

关于模拟机制的其他说明

Emulated模式通常对我们来说是透明的,因为我们更喜欢把我们的全局样式(影响ComponentParentComponentChild),它将渗透到NoneEmulated组件及其子组件和HTML元素中。
然而,假设ComponentChild是第三方组件,并且您希望对其进行样式化。如果在ComponentParent组件上应用Emulated模式,则无法进行样式化。这是由于Emulated实现所致:

ComponentParent组件内的每个HTML元素都将使用component-name属性(无值)进行修饰,例如:
*一米二十六分一x:对于组件容器
*一米二十七分一x:对于组件的内容

同时,我们的组件ComponentParent中的每个CSS选择器都将使用相同的component-name属性进行“封装”(条件化

.H1[_ngcontent-c3] {
  background-color:yellow;
}

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

针对第三方组件的解决方案

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

wqnecbli4#

from pro-angular book:

视图封装值:
*模拟:当指定此值时,Angular通过编写内容和样式以添加属性来模拟阴影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或使用多边形填充时,此功能才有效。
***None:**当指定此值时,Angular只是将未修改的CSS样式添加到HTML文档的head部分,并让浏览器使用正常的CSS优先级规则来确定如何应用样式。

  • 使用Native和None值时应谨慎。浏览器对shadow DOM功能的支持非常有限,因此只有在使用与其他浏览器兼容的多边形填充库时,使用Native选项才是明智的。*
  • “无”选项将组件定义的所有样式添加到HTML文档的head部分,并让浏览器确定如何应用它们。这样做的好处是可以在所有浏览器中使用,但结果是不可预测的,并且不同组件定义的样式之间没有隔离。*
o7jaxewo

o7jaxewo5#

如果有人因为想通过父组件样式声明来设置子组件的样式而遇到这个问题,请参见this SO answer
然而,正如对公认答案的最新评论所表明的那样,Angular文档说:
穿透阴影的后代组合符已被弃用,主要的浏览器和工具也将不再支持它。因此,我们计划在Angular中不再支持它(/deep/,〉〉〉和::ng-deep)。在此之前,应该首选::ng-deep以获得与这些工具更广泛的兼容性。

ahy6op9u

ahy6op9u6#

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

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

Click here以查看示例

相关问题