【问题标题】:how to change the global variable inside a scss mixin如何更改scss mixin中的全局变量
【发布时间】:2019-05-24 03:57:14
【问题描述】:

主题变量.scss

//---------------------------------------------------------
//Declare a global variable and set it to red color
//---------------------------------------------------------
$fg-primary-text: red; 

//---------------------------------------------------------
//below @mixin is used in styles.scss to pass the custom-theme
//---------------------------------------------------------
@mixin cache-theme-colors($theme) {
   @include set-global-variables($theme);
}

//---------------------------------------------------------
//local mixin to set the global-variable from the $theme using !global flag
//---------------------------------------------------------
@mixin set-global-variables($theme: $theme, $fg-primary-text: $fg-primary-text) {
 $foreground: map-get($theme, foreground); //get foreground from the theme
 $fg-primary-text: mat-color($foreground, text) !global; //get the text color from the theme and set it here using the !global flag

}

组件.scss

@import "../../../../assets/themes/theme-variables.scss";

.text-color {
    color: $fg-primary-text;  //use the variable (but it is still red)
}

但颜色还是红色 我的问题是:如何在 scss 中设置全局变量并在 mixin/function 中更改它并在任何 component.scss 中使用它

【问题讨论】:

    标签: sass angular-material2 scss-mixins


    【解决方案1】:

    您需要在您的 component.scss 中添加一个 mixin 函数。

    然后在您的 main.scss 文件中添加一个 @include。

    component.scss

    @mixin text-color-mixin($theme) {
      $is-dark-theme: map-get($theme, is-dark);
      .text-color {
        color: if($is-dark-theme, red, blue);
      }
    }
    

    ma​​in.scss

    @import ..<path to file>.../component.scss
    ...
    <Other code>
    ...
    @include  text-color-mixin($theme);
    

    要了解有关如何构建 Angular 项目主题的更多信息,您可以查看 https://github.com/angular/material.angular.io

    这是 angular material io 文档站点的官方 repo。

    编辑

    我想这也回答了你的问题

    How to manipulate scss variables in Angular2 components

    【讨论】:

    • 这就是问题所在,当我动态更改主题时,我需要将其传递给我的所有组件。说如果我有 130 多个组件,那么我必须使用所有 130 多个组件的 @include 混合。当我更改主题并在任何组件中使用它时,将颜色值存储在全局变量中会更好。
    • 你不能让 scss 编译成 css 并且样式表中没有变量这样的东西。但即使你有 200 个变量,如果你只是从主题派生 css 类,我也不明白为什么你必须将 css 类放在所有 130 多个组件中。您可以将其包含在 main.scss 文件中,然后在所有组件中使用该 css 类。您正在做一个特定的用例吗?
    • 实际要求是: 1) 我们需要一个单独的全局颜色变量文件,其中包含所有的$color-variables。 2) 当应用程序主题改变时,将 $theme 对象传递给全局颜色变量文件并从主题中填充那些 $color-variable,3) 现在在任何组件中导入颜色文件,4) 使用颜色变量来设置样式你的 html 元素。
    【解决方案2】:

    我终于找到了解决方案,我在这里分享给需要的人。

    注意:我知道它很长.. 但请耐心阅读您可能会有所收获 如果我做错了什么,请纠正我。

    首先从theme.service开始

    theme.service.ts

    import { Injectable } from '@angular/core';
    import { OverlayContainer } from '@angular/cdk/overlay';
    
    @Injectable({ providedIn: 'root' })
    export class ThemeService {
    
      constructor(private overlayContainer: OverlayContainer) {}
    
      currentThemeNAME: string = "light-theme";
      //DEFAULT_THEME
      private defaultThemeNAME: string = "light-theme";
      setDefaultTHEME() {
        this.setTHEME(this.defaultThemeNAME);
      }
    
      //LIGHT_THEME
      private lightThemeNAME: string = "light-theme";
      setLightTHEME() {
        this.setTHEME(this.lightThemeNAME);
      }
    
      //DARK_THEME
      private darkThemeNAME: string = "dark-theme";
      setDarkTHEME() {
        this.setTHEME(this.darkThemeNAME);
      }
    
      //TO_SET_THE_THEME
      setTHEME(themeNAME: string) {
        console.log(themeNAME);
        this.currentThemeNAME = themeNAME;
        this.overlayContainer.getContainerElement().classList.add(this.currentThemeNAME);
      }
    
      //TO_CYCLE_THE_THEME
      cycleTHEME() {
        switch (this.currentThemeNAME) {
          case this.lightThemeNAME:
            this.setDarkTHEME();
            break;
          case this.darkThemeNAME:
            this.setLightTHEME();
            break;
        }
      }
    
    }

    app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { NgModule } from '@angular/core';
    import { RouterModule } from '@angular/router';
    import { FlexLayoutModule } from '@angular/flex-layout';
    
    //CORE-SERVICES
    import { ThemeService } from './core/services/theme.service';
    
    @NgModule({
      entryComponents: [...],
      declarations: [...],
      exports: [...],
      imports: [...],
    
    
      providers: [ ThemeService ], //<----Important
    
      bootstrap: [AppComponent],
    })
    
    export class AppModule {
      //important
      constructor(private themeSRVC: ThemeService) {
        this.themeSRVC.setDefaultTHEME(); //<----Important
      }
    
    }

    假设我有 2 个主题

    1) light-theme.scss

    // define 3 theme color
    // mat-palette accepts $palette-name, default, lighter and darker variants
    
    $light-theme-primary: mat-palette($mat-grey, 500, 100, 700);
    $light-theme-accent: mat-palette($mat-pink);
    $light-theme-warn: mat-palette($mat-red);
    
    // create theme (use mat-dark-theme for themes with dark backgrounds)
    $light-theme: mat-light-theme( $light-theme-primary, $light-theme-accent, $light-theme-warn);

    2) 黑暗主题.scss

    // define 3 theme color
    // mat-palette accepts $palette-name, default, lighter and darker variants
    
    $dark-theme-primary: mat-palette($mat-grey, 900, 700, 900);
    $dark-theme-accent: mat-palette($mat-blue-grey);
    $dark-theme-warn: mat-palette($mat-red);
    
    // create theme (use mat-dark-theme for themes with dark backgrounds)
    $dark-theme: mat-dark-theme($dark-theme-primary, $dark-theme-accent, $dark-theme-warn);

    styles.scss

    /* You can add global styles to this file, and also import other style files */
    
    @import './assets/fonts/roboto/stylesheet.css';
    @import './assets/icons/material-icons/v42/stylesheet.css';
    
    //important
    @import '~@angular/material/theming';
    
    //important: always include only once per project
    @include mat-core();
    
    //important: import our custom theme files here
    @import './assets/themes/light-theme.scss';
    @import './assets/themes/dark-theme.scss';
    
    //important: import the theme cacher
    @import './assets/themes/register_components.scss';
    
    html,
    body {
      height: 100%;
      padding: 0px;
      margin: 0px;
      font-family: Roboto;
    }
    
    // to set this theme: 
    // set yout component's root element's class
    // example-1: <body class="dark-theme"> ... </body>
    // example-2: <form [ngClass]="themeSRVC.currentThemeNAME"
    
    .light-theme {
      @include angular-material-theme($light-theme); //set material_theme
      @include set-components-theme($light-theme); //cache_theme
    }
    
    // to set this theme: 
    // set yout component's root element's class
    // example-1: <body class="dark-theme"> ... </body>
    // example-2: <form [ngClass]="themeSRVC.currentThemeNAME"
    
    .dark-theme {
      @include angular-material-theme($dark-theme); //set material_theme
      @include set-components-theme($dark-theme); //cache_theme
    }
    
    //...similarly register your other themes here

    register_components.scss

    @import '~@angular/material/theming';
    @import '../src/app/erp/security/erp-login/erp-login.component.scss';
    @import '../src/app/erp/dashboard/dashboard.component.scss';
    @mixin set-components-theme($theme) {
      //###################################################################################
      //---STEP-(1/3): EXTRACT_PALLETE_AND_COLORS----------
      //https://github.com/angular/material2/blob/master/src/lib/core/theming/_palette.scss
      //https://github.com/angular/material2/blob/master/src/lib/core/ripple/_ripple.scss
      //###################################################################################
      //---01-PRIMARY---------------------
      $primary-palette: map-get($theme, primary); //<---
      $primary-color: mat-color($primary-palette, default);
      $primary-light: mat-color($primary-palette, lighter);
      $primary-dark: mat-color($primary-palette, darker); //<---
      //---02-ACCENT----------------------
      $accent-palette: map-get($theme, accent); //<---
      $accent-color: mat-color($accent-palette, default);
      $accent-light: mat-color($accent-palette, lighter);
      $accent-dark: mat-color($accent-palette, darker); //<---
      //---03-WARN------------------------
      $warn-palette: map-get($theme, warn); //<---
      $warn-color: mat-color($warn-palette, default);
      $warn-light: mat-color($warn-palette, lighter);
      $warn-dark: mat-color($warn-palette, darker); //<---
      //---04-FOREGROUND------------------
      $foreground-palette: map-get($theme, foreground); //<---
      $fg-base: mat-color($foreground-palette, base); //full_black or full_white
      $fg-primary-text: mat-color($foreground-palette, text);
      $fg-secondary-text: mat-color($foreground-palette, secondary-text);
      $fg-hint-text: mat-color($foreground-palette, hint-text);
      $fg-disabled: mat-color($foreground-palette, disabled);
      $fg-disabled-button: mat-color($foreground-palette, disabled-button);
      $fg-disabled-text: mat-color($foreground-palette, disabled-text);
      $fg-divider: mat-color($foreground-palette, divider);
      $fg-dividers: mat-color($foreground-palette, dividers);
      $fg-elevation: mat-color($foreground-palette, elevation);
      $fg-icon: mat-color($foreground-palette, icon);
      $fg-icons: mat-color($foreground-palette, icons);
      $fg-slider-min: mat-color($foreground-palette, slider-min);
      $fg-slider-off: mat-color($foreground-palette, slider-off);
      $fg-slider-off-active: mat-color($foreground-palette, slider-off-active); //<--
      //---05-BACKGROUND------------------
      $background-palette: map-get($theme, background); //<---
      $bg-color: mat-color($background-palette, background);
      $bg-status-bar: mat-color($background-palette, status-bar);
      $bg-app-bar: mat-color($background-palette, app-bar);
      $bg-hover: mat-color($background-palette, hover);
      $bg-card: mat-color($background-palette, card);
      $bg-dialog: mat-color($background-palette, dialog);
      $bg-disabled-button: mat-color($background-palette, disabled-button);
      $bg-raised-button: mat-color($background-palette, raised-button);
      $bg-focused-button: mat-color($background-palette, focused-button);
      $bg-selected-button: mat-color($background-palette, selected-button);
      $bg-selected-disabled-button: mat-color($background-palette, selected-disabled-button);
      $bg-disabled-button-toggle: mat-color($background-palette, disabled-button-toggle);
      $bg-unselected-chip: mat-color($background-palette, unselected-chip);
      $bg-disabled-list-option: mat-color($background-palette, disabled-list-option); //<---
      //---COMMON_COLORS---------------
      //fetch from the theme directly using the is_dark_mode flag
      $is-dark-theme: map-get($theme, is-dark); //<---
      //primary_text
      $fg-dark-primary-text: rgba(black, 0.87);
      $fg-light-primary-text: white;
      $fg-primary-text-inverse: if($is-dark-theme, $fg-dark-primary-text, $fg-light-primary-text); //<---
      //secondary_text
      $fg-dark-secondary-text: rgba(black, 0.54);
      $fg-light-secondary-text: rgba(white, 0.7);
      $fg-secondary-text-inverse: if($is-dark-theme, $fg-dark-secondary-text, $fg-light-secondary-text); //<---
      //disabled_text
      $fg-dark-disabled-text: rgba(black, 0.38);
      $fg-light-disabled-text: rgba(white, 0.5);
      $fg-disabled-text-inverse: if($is-dark-theme, $fg-dark-disabled-text, $fg-light-disabled-text); //<---
      //dividers
      $bg-dark-dividers: rgba(black, 0.12);
      $bg-light-dividers: rgba(white, 0.12);
      $bg-dividers-inverse: if($is-dark-theme, $bg-dark-dividers, $bg-light-dividers); //<---
      //focused
      $bg-dark-focused: rgba(black, 0.12);
      $bg-light-focused: rgba(white, 0.12);
      $bg-focused-inverse: if($is-dark-theme, $bg-light-focused, $bg-light-focused); //<---
      //---DERIVED_COLORS--------------
      $_bg-ripple: rgba($fg-base, 0.1); //SPEC
      $_bg-list-item: $bg-card;
      $_scrollbar-bg: rgba($fg_icon, .4);
      $_scrollbar-fg: rgba($fg_icon, .05);
      $_scrollbar-hover-bg: rgba($fg_icon, .16);
      $_scrollbar-hover-fg: rgba($fg_icon, .20); //<----
      //###################################################################################
      //---STEP-(2/3): CREATE_GLOBAL_CLASSES_THAT_DEPEND_ON_THE_ABOVE_THEME_COLORS--
      //###################################################################################
      //++++++MAT-LIST-ITEM++++++++++++++++++++++++++++
      .mat-list-item {
        background-color: $_bg-list-item;
      }
      .mat-list-item.selected {
        background-color: $primary-light;
      }
      .mat-list-icon {
        color: $fg_icon;
      } //<---
      //###################################################################################
      //---STEP-(3/3): PASS_REQUIRED_COLORS_TO_THE_COMPONENTS-----(note: not the $theme)
      //###################################################################################
      //---Pass_Colors_required_by_the_DashboardComponent
      @include dashboard-component-theme( //---
        $fg-primary-text, $fg-secondary-text, //---
        $fg-primary-text-inverse, $fg-secondary-text-inverse, //---
        $_bg-ripple); //<--
    
      //---Pass_Colors_required_by_the_erp-Component
      @include erp-component-theme($fg-primary-text, $fg-secondary-text);
    
     //similarly register all your components here and pass only the required colors
    } //--------------------------------------------

    dashboard.component.scss

    @import '~@angular/material/theming';
    
    //colors_passed_by_the register_component.scss
    
    @mixin dashboard-component-theme(    
        $fg-primary-text, $fg-secondary-text, 
        $fg-primary-text-inverse, $fg-secondary-text-inverse, 
        $_bg-ripple) {
     
        //Classes for component's html
        
        .sidenav-header-primary-text {
            color: $fg-primary-text-inverse;
            font-size: 18px;
            line-height: 28px;
            margin-bottom: 8px;
        }
        
        .sidenav-header-secondary-text {
            color: $fg-secondary-text-inverse;
            font-size: 15px;
            line-height: 15px;
            margin-bottom: 2px
        }
        
        .list-item-primary-text {
            color: $fg-primary-text;
        }
        
        .list-item-secondary-text {
            color: $fg-secondary-text;
        }
        
    }

    dashboard.component.ts

    @Component({
      selector: 'app-dashboard',
      templateUrl: './dashboard.component.html',
      styleUrls: ['./dashboard.component.scss'],
    
    })
    export class DashboardComponent implements OnInit {
    
      //###-Important: include the ThemeService
      constructor(private themeSRVC: ThemeService) {
        //...
      }
     
      //...
      
       //---
    }

    dashboard.component.html

    <!-- Important set [ngClass] of the root element from the themeSRVC -->
    
    <mat-sidenav-container [ngClass]="themeSRVC.currentThemeNAME">
    
    
      <!-- .... -->
    
      <!-- Include the classes from the component's scss -->
    
      <h4 class="list-item-primary-text" mat-line>456</h4>
      <p class="list-item-scondary-text" mat-line>123</p>
    
    
      <!-- .... -->
    
    </mat-sidenav-container>

    就是这样..!

    【讨论】:

      猜你喜欢
      • 2020-03-31
      • 2019-06-09
      • 2018-09-23
      • 2018-11-23
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多