Инкапсуляция представления стиля компонента Angular не работает, когда файл scss компонента импортируется в файл scss стилей

Представьте, что внутри файла my.component.scss компонента Angular есть миксин SCSS.

Теперь я импортирую этот файл в глобальный style.scss приложения Angular, потому что хочу передать некоторые данные в этот миксин.

Например: 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>

Файл 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 должен иметь инкапсулированный класс css «сообщение об ошибке», и его видимость должна быть ограничена только моим компонентом. Как в этом случае сохранить работоспособность инкапсуляции?

PS: Я просто пытаюсь выполнить следующее: https://material.angular.io/guide/theming#theming-only-specific-components, но эта проблема, похоже, носит более общий характер.

Заранее спасибо. Дайте мне знать, если нужны дополнительные пояснения или код.


person kashpatel    schedule 07.06.2018    source источник


Ответы (1)


Тематика и инкапсуляция стиля - это разные вещи. Angular инкапсулирует код стиля только в таблице стилей вашего компонента; он не инкапсулирует какие-либо определенные там миксины, потому что миксины должны быть вызваны для применения. И то, где вы определяете миксин, не имеет ничего общего с тем, где применяется миксин - это решать вам. Ваш класс ошибки доступен для всего приложения, потому что вы вызвали его («включили») в свою основную таблицу стилей.

В конечном итоге вы не можете использовать темы и инкапсулировать их, потому что способ их работы зависит от всего приложения. Итак, чтобы обойти это, используйте селектор вашего компонента, чтобы ограничить область действия класса в вашем миксине:

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

Это по-прежнему определяет стиль приложения в целом, но повлияет только на ваш компонент.

Кроме того, вам не следует включать миксины тематики компонентов в таблицы стилей компонентов. Они должны быть в собственном файле тем, чтобы при импорте миксина для темы вы также не импортировали - в свою основную таблицу стилей приложения - любые стили, не связанные с темой, для компонента.

При этом вы можете попробовать инкапсулировать тематику компонентов. Вам нужно будет получить доступ к своей глобально определенной теме в таблице стилей вашего компонента, и вам также, возможно, придется импортировать утилиты тематики материала angular в свою таблицу стилей компонента. Я не уверен, что это сработает, и я думаю, что это может добавить много дублирования стилей в ваше приложение, если вы сделаете это для большого количества компонентов.

person G. Tranter    schedule 08.06.2018
comment
Большое спасибо. Я уже знал, что могу обернуть CSS в селекторах компонентов, но это не 100% инкапсуляция стиля. Было просто более любопытно, есть ли лучший способ, о котором я не знаю. Сейчас я просто буду использовать селектор компонентов. - person kashpatel; 13.06.2018
comment
Пожалуйста, проголосуйте за или примите, если вы нашли мой ответ полезным. Спасибо. - person G. Tranter; 13.06.2018