如何为Web组件动态设置ViewEncapsulation?

时间:2019-04-18 12:23:39

标签: angular web-component

我试图基于浏览器初始化带有或不带有Shadow DOM的组件(因为IE不支持Shadow DOM)。

我检查它是否为IE11,并将IE的封装设置为Emulated,对于其他浏览器,将封装设置为ShadowDom

const agent = window.navigator.userAgent;
const isIe11 = agent.indexOf('MSIE') === -1 && agent.indexOf('Trident') > 0;

@Component({
   selector: 'my-web-component',
   templateUrl: '...html',
   styleUrls: ['...scss'],
   encapsulation: isIe11 ? ViewEncapsulation.Emulated : ViewEncapsulation.ShadowDom
})
export class NavbarComponent implements OnInit { ... }

根据浏览器检查的返回值,isIe11的值是正确的,但是封装总是以ViewEncapsulation.Emulated结束。

我通过DOM检查器确认了这一点,因为在DOM中看不到#shadow-root。相反,我看到_ngcontent-c0确认封装已被仿真。

1 个答案:

答案 0 :(得分:1)

这在您设想的方式中是不可能的,因为angular在AOT模式下编译您的代码,并且在编译步骤中显然不知道浏览器。

我只能想到一种实现此目标的方法。您必须两次编译同一应用程序。对于不兼容ShadowDom的浏览器,一次,并且可能的话。

然后,根据浏览器的请求,在服务器上为您提供所需的服务。我想您还可以在index.html内找到一种破解方法,该方法将根据当前浏览器加载正确的角度库。这将需要一些ng build之后的脚本。

不过,您可以从环境文件中处理所需的封装,因此,如果对于兼容和不兼容的浏览器有两种不同的环境,则可以在环境中添加一个属性:

// non shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.Emulated
}


// shadow dom compatible env
export const environment = {
  // ...
  defaultEncapsulation: ViewEncapsulation.ShadowDom
}

如果您的生产版本具有这两个环境文件,则可以在bootstrapModule中编辑main.ts方法以读取值:

platformBrowserDynamic().bootstrapModule(AppModule, {
  defaultEncapsulation: environment.defaultEncapsulation
});