ViewEncapsulation.Emulated 样式通过 ViewEncapsulation.(Native|ShadowDom) 组件复制到#shadow-root

ViewEncapsulation.Emulated styles are copied into #shadow-root by a ViewEncapsulation.(Native|ShadowDom) component

我有一个示例存储库 https://github.com/collinstevens/angular-encapsulation 可以证明我的问题。

一共有三个组件:EmulatedComponent、NativeComponent、ShadowDomComponent,分别使用ViewEncapsulation.Emulated、ViewEncapsulation.Native、ViewEncapsulation.ShadowDom。

EmulatedComponent 的样式被复制到 <head> 中,如 https://angular.io/guide/component-styles 中所述,但也被复制到每个 #shadow-root 中,我想知道为什么,以及如何防止如果可能的话。

emulated.component.scss

div {
  width: 50px;
  height: 50px;
  background-color: black;
  display: inline-block;
}

native.component.scss

div {
  width: 50px;
  height: 50px;
  background-color: red;
  display: inline-block;
}

shadow-dom.component.scss

div {
  width: 50px;
  height: 50px;
  background-color: yellow;
  display: inline-block;
}

三者的主要区别:

1- ViewEncapsulation.Emulated 它预处理 css 代码到组件的深层范围以防止冲突,这是 angular 的默认模式,因为影子 dom 支持有限在浏览器中...浏览器支持 can i use

根据 angular 文档 Read

2- ViewEncapsulation.Native 使用已弃用的影子版本 dom。 它的工作原理几乎与 shadow dom encapsulation

相同

3- ViewEncapsulation.ShadowDom 当您使用 ShadowDom 时,为什么会在每个 #shadow-root 中复制样式,因为这就是它的工作方式...当您激活 ShadowDom 时,它允许隐藏的 DOM 树附加到常规树它就像常规 DOM 树中的树因此它通过制作高级范围复制应用于元素的样式,你实际上看到的是阴影 dom 但理论上是常规 DOM...

有关 Shadow 的更多进一步阅读 Dom MDN article

最佳实践和 angular 团队推荐使用 ViewEncapsulation.Emulated,这是默认设置,但在极少数情况下,您使用 NoneShadowDom,但将其与注意。

这是已知的bug,目前的解决方法是基本上不混合封装模式。

但我假设您遇到的情况可能是您正在混合具有不同类型封装模式的第三方?如果是这样,您要么必须考虑您的 css 结构,要么只是重新考虑您正在混合的第三方库。

更新

考虑到注释,通过告诉编译器使用 compilerOptions 将所有组件设为 运行 本机封装,以免与本机 Web 组件冲突。

通过在您的 tsconfig.json 文件中添加(在 ng 版本 6+ 中是 tsconfig.app.json):

"angularCompilerOptions": {
    "defaultEncapsulation": 1
}