关于sass:将组件scss文件导入样式scss文件时,Angular组件的样式视图封装不起作用

Angular component's style view encapsulation does not work when component scss file is imported to styles scss file

想象一下,Angular组件的my.component.scss文件中有一个SCSS mixin。

现在,我要在Angular应用程序的global.scss中导入该文件,因为我想将一些数据传递给该mixin。

例如:
my-component.scss。

1
2
3
4
5
6
7
8
9
10
11
[cc]
 @mixin my-component-theming($theme) {
     // Extract whichever individual palettes you need from the theme.
     $warn-palette: map-get($theme, warn);

     $warn: mat-color($primary-palette);

     .error-message {
        color: $warn !important;
      }
   }

我的component.ts

1
2
3
4
5
6
7
[cc]

 @Component({
   selector: 'my-component',
   templateUrl: './my-component.html',
   styleUrls: ['./my-component.scss']
})

Angular应用程序的styles.scss。 (这将导入Angular.json)

1
2
3
4
5
6
7
8
[cc]
    @import '~@angular/material/theming';
    @import 'my-component.scss';

    // just imagine that $app-theme is already defined here.
    // Not including unnecessary code to keep example simple.

    @include my-component-theming($app-theme)

它确实可以按预期进行编译和应用程序工作,但是整个应用程序都可以访问我的"错误消息" css类。

Angular应该已经封装了"错误消息" css类,并且它的可见性应该仅限于my-component。在这种情况下,如何保持封装正常工作?

PS:我只是想做到这一点:https://material.angular.io/guide/theming#theming-only-certain-components,但是这个问题似乎更笼统。

提前致谢。让我知道是否需要进一步说明或代码。


主题和样式封装是两件事。 Angular只会将样式代码封装在组件的样式表中;它没有封装在那里定义的任何混合包,因为必须调用混合包才能应用。定义混合的位置与应用混合的位置无关-这取决于您。您可以在整个应用程序中访问您的错误类,因为您已在主样式表中对其进行了调用("包含")。

最终,您不能使用主题并将其封装,因为主题的工作方式是整个应用程序范围。因此,为了解决这个问题,请使用组件的选择器来限制mixin中类的范围:

1
2
3
4
5
6
7
8
9
10
@mixin my-component-theming($theme) {
  // Extract whichever individual palettes you need from the theme.
  $warn-palette: map-get($theme, warn);

  $warn: mat-color($primary-palette);

  my-component.error-message {
    color: $warn !important;
  }
}

这仍然在整个应用程序中定义了样式,但是只会影响您的组件。

此外,您不应在组件样式表中包括组件主题混合。它们应位于自己的主题文件中,以便在导入用于主题的mixin时,也不会将组件的任何非主题样式都导入到主应用程序样式表中。

话虽如此,您可以尝试封装组件主题。您可能需要访问组件样式表中的全局定义主题,并且可能还必须将角度材质主题实用程序导入到组件样式表中。我不确定这是否行得通,并且如果您对许多组件执行此操作,则可能会在您的应用程序中添加很多样式重复。