【问题标题】:Angular component's style view encapsulation does not work when component scss file is imported to styles scss file组件scss文件导入样式scss文件时,Angular组件的样式视图封装不起作用
【发布时间】:2018-11-17 16:52:27
【问题描述】:

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

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

例如: my-component.scss.

<pre>
 @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;
      }
   }
</pre>

my-component.ts

<pre>

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

</pre>

Angular 应用的styles.scss。 (这会在 Angular.json 中导入)

<pre>
    @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)
</pre>

它确实按预期编译和应用程序工作,但我的“错误消息”css 类可供整个应用程序访问。

Angular 应该已经封装了“error-message”css 类,并且它的可见性应该仅限于 my-component。在这种情况下如何保持封装工作?

PS:我只是想完成这个:https://material.angular.io/guide/theming#theming-only-certain-components 但这个问题似乎更普遍。

提前致谢。如果需要进一步说明或代码,请告诉我。

【问题讨论】:

    标签: angular sass angular-material angular6 angular-material-theming


    【解决方案1】:

    主题和样式封装是两个不同的东西。 Angular 只会将样式代码封装在组件的样式表中;它没有封装在那里定义的任何mixin,因为必须调用mixin才能应用。你定义 mixin 的位置与应用 mixin 的位置无关——这取决于你。整个应用程序都可以访问您的错误类,因为您已在主样式表中调用(“包含”)它。

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

    @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 时,您不会同时将组件的任何非主题样式导入到您的主应用程序样式表中。

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

    【讨论】:

    • 非常感谢。我已经知道我可以将 css 包装在组件选择器中,但这不是 100% 的样式封装。如果有任何我不知道的更好的方法,我会更加好奇。我现在只使用组件选择器。
    • 如果您觉得我的回答有用,请投票或接受。谢谢。