微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在导出的 Web 组件中封装 Angular 应用的全局 CSS?

如何解决如何在导出的 Web 组件中封装 Angular 应用的全局 CSS?

目标

我有一个 Angular 11 站点,其中包含一个使用 Angular Material 的大型表单组件——我们称之为 myExportableComponent。我想像往常一样在我的网站中使用 myExportableComponent,但将其导出为通用 Web 组件(也称为“自定义元素”,也称为“角度元素”)。这样,它就可以在任何 3rd 方网站上使用,无论他们的技术堆栈如何,而且它的工作方式与在我的网站上完全相同。

myExportableComponent 应该像我网站中的普通 Angular 组件一样工作 - 它应该可以通过 styles.scss 中的全局 CSS 和 my-exportable.component.scss 中的组件特定 CSS 设置样式。>

当用作 Web 组件时,myExportableComponent 也应该像平常一样受到全局和特定于组件的 CSS 的影响,但这些 CSS 不应泄漏并影响它所在的​​第 3 方页面的其余部分放置。这是我正在努力解决的部分。

设置

我在主项目的子项目中设置了 myExportableComponent。我可以单独构建它并获取生成的 js/css 文件并在另一个站点中成功使用 web 组件。像这样:

<link rel="stylesheet" href="myExportableComponentStyles.css">
<script type="text/javascript" src="myExportableComponent.js"></script>

<div class="mat-app-background mat-typography">
    <my-exportable-component></my-exportable-component>
</div>

我已经让 myExportableComponent 与我的主站点共享所有样式,方法是进入 angular.json,并将其指向主应用程序的 theme.scss 文件生成的 Angular 材质主题)和 {{ 1}}(其他全局样式)。这样的事情...

angular.json:

styles.scss

问题

在其他站点上使用 Web 组件时,不会封装全局 CSS。例如,如果我在 "mainApp": { ... "styles": [ "src/theme.scss","src/styles.scss" ],"myExportableComponentApp": { ... "styles": [ "src/theme.scss",//NOT "projects/myExportableComponentApp/src/theme.scss" "src/styles.scss" //NOT "projects/myExportableComponentApp/src/styles.scss" ], 中为我的应用添加全局链接样式,它也会影响消费站点上的所有链接styles.scss (Material) 样式似乎没有泄漏,但我认为那是因为那些东西已经使用了自定义选择器。如果消费站点碰巧也使用 Angular Material,我担心它泄漏。

想法 1:封装设置

我想尝试在 theme.scss 上使用 encapsulation: ViewEncapsulation.ShadowDom,但是 A) 破坏了一些 Material 样式和图标,并且 B) 无论如何这并不是我真正想要的,因为那是组件级封装和我的问题是全局 CSS。实际上,我的组件特定 CSS 似乎已经被认设置封装了。

想法 2:仅将全局 CSS 定位到我的 HTML

如果我在应用程序的 HTML 标签添加一个类,并让 Web 组件的使用者也将它添加到组件周围,我可以将所有全局 CSS 规则定位为仅影响这些容器内的内容,例如:

myExportableComponent

这实际上确实可以从 3rd 方页面封装我的全局样式,但它以某种方式翻转了样式,以便全局样式在不应该优先于特定于组件的样式时优先。

想法 3:在我的全局 CSS 上使用 :host 或 :host-context 选择器?

老实说,我很难掌握这些,而且我无法让它们在我的应用中执行任何操作。

想法 4:构建时脚本?

.special-wrapper a { /* some style*/ } 的子项目构建完成后,如果我能自动myExportableComponenttheme.scss 中剪切所有全局 CSS 并将其粘贴到 styles.scss 的顶部,我认为那会奏效。我的“全局”样式将被封装到我的 Web 组件中,因为它们位于特定于组件的文件中。

当我运行 my-exportable.component.scss 时是否可以做这样的事情?我不知道从哪里开始。

我愿意接受建议!

解决方法

这是我最终做的:

  1. 从子项目的 style.scss 删除站点的全局 angular.json

  2. 创建一个继承自 myExportableComponent 的新组件,但除此之外没有代码。它也没有自己的模板——它共享基本组件的模板。您实际上甚至不需要从子项目中的模块中导出此组件。这样主应用默认只能使用基础的,这很好。

  3. 新子组件的 styleUrls 有两个文件。首先是特定于组件的样式表。它的设置与正常一样,但在它内部只有一个引用主站点全局样式表的导入,类似于 @import '../../../../../../src/app/styles.scss';。我想直接引用它,但不断收到奇怪的构建错误,因此将它导入到“普通”特定于组件的样式表中的技巧是有效的。第二个文件是对 base 组件的常规组件特定样式表的引用。

  4. 为 Web 组件执行 createCustomElement 时,使用子组件而不是父组件。

最重要的是,在构建通用 Web 组件时,主站点的全局 css 将包含在 myExportableComponent 的组件特定 css 的顶部,而不是全局的。然后封装全局样式,并且仍然可以像正常一样被特定于组件的样式覆盖。

我想对包含 Material 主题的 theme.scss 做同样的事情,但它似乎只有在它真正在全局范围内 (https://github.com/angular/components/issues/3386) 时才有效。目前这对我来说不是一个交易破坏者。

优点:

  • 主站点项目没有特殊设置或中断。它和 myExportableComponent 可以在我们的主应用中以完全标准的方式使用。
  • 样式封装在导出的 Web 组件中的工作方式与在我们的主项目中的工作方式相同,并且不会泄露到 3rd 方网站。
  • 不需要特殊的构建脚本

缺点:

  • 这有点不正统,您需要确保其他开发人员不会在用作此构建解决方案管道的虚拟/继承文件中放置任何内容。
  • 据我所知,Material 主题 css 尚不可行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。