2

我正在使用 Laravel Mix 和 Webpack 进行 SASS 预处理。

我的网站中有两个“主题”,我想精简它们,在需要的地方继承变量。例如,我的主要主题将按以下顺序包括:

// Primary theme
@import "./primary-variables.scss";
@import "/path/to/default/theme/main.scss";

我的默认主题如下所示:

// Default theme
@import "./default-variables.scss";
@import "~bootstrap-sass/assets/stylesheets/_bootstrap";

与这个问题类似,我首先包含了主要变量,然后是默认主题变量,最后是引导程序。

在我的默认主题中,我添加!default了所有变量,以便在重新定义 Bootstrap 的地方优先使用它们,而在新的地方,它们将成为默认值。主要主题根本不使用!default

工作示例

如果 Bootstrap 定义$brand-danger为 say red !default,我的默认主题将其重新定义为blue !default并且我的主主题将其重新定义为yellow,我的渲染输出将是黄色的 - 太棒了!

问题

当我需要引用仅在我的主要主题的其他级别定义的变量时。例如:

// Primary theme:
// This fails since I haven't defined $brand-primary in my primary theme
$my-primary-theme-variable: $brand-primary;

构建现在失败并显示错误消息primary-theme/src/scss/main.scss doesn't export content

解决方法

我可以通过将整个 Bootstrap 变量文件复制到我的主主题并根据需要更改变量来解决这个问题,但我真的不想这样做。

问题

SASS 变量处理器实际上是如何工作的?我是否可以只更改主题中的 Bootstrap 变量之一,而不必重新定义整个文件?


这个问题很相似。

4

2 回答 2

3

似乎您正在使用@include导入您的 SCSS 尝试使用@import代替 - 如果这只是问题中的错字,请告诉我:-)

@import "./primary-variables.scss",
        "/path/to/default/theme/main.scss"
;

我已经就您所指的问题添加了一些快速注释。关于!default标志需要了解的重要一点是,它在选择器中使用时生效,并且不会重新定义变量。

Sass 在处理变量时不会向前看——它会打印出当前值。在这个例子中 .class-1 将是红色的,因为它在选择器中使用后重新定义,而 .class-2 将是蓝色的,因为没有默认标志。

$brand-color: red !default; // defined
.class-1 { background-color: $brand-color; }  // red

$brand-color: blue;         // re-defined
.class-2 { background-color: $brand-color; }  // blue

默认标志将导致 Sass 跳过变量重新定义。在此示例中,结果将是红色的,因为首先定义。由于默认标志,以下两个重新定义被忽略。

$brand-color: red !default;   // defined
$brand-color: blue !default;  // ignored 
$brand-color: green !default; // ignored
.class-1 { background-color: $brand-color; }  // red

在这种情况下,将使用来自配置的所有变量 - 如果未在配置中定义,则来自部分 1 的变量和最后一个部分 2 将定义未在其他两个中定义的任何变量。

@import '_config.scss';    // definition
@import '_partial-1.scss'; // contains defaults
@import '_partial-2.scss'; // contains defaults

希望这是有道理的:-)


导入结构

//  _default-theme.scss
@import '_default-variables.scss', '_bootstrap.scss';

//  _primary-theme.scss
//  primary variables will override defaults or use defaults if not defined
@import '_primary-variables.scss', '_default-theme.scss';

// style.scss
@import '_primary-theme.scss'; // or '_default-theme.scss'

范围

如果您的默认和主要内容具有每个主题独有的内容,您可以创建一个范围混合来处理编译的内容。

这是一个非常基本的版本:

//  _scope.scss
$scope-context: null !default;
@function scope($scopes: null, $true: true, $false: false) { 
  @each $scope in $scope-context {  
    @if index($scopes, $scope) { @return $true }  
  }  
  @return $false;  
} 
@mixin scope($scopes: null) { 
  @if scope($scopes) or length($scopes) == 0 and not $scope-context { 
    @content; 
  } 
}

这个怎么运作

范围 mixin 接受一个上下文参数和一个内容块@content。如果传递的上下文与全局变量($scope-context)匹配,则呈现内容块。

//  _default-theme.scss
.class { content: 'Will show in both themes'; }

@include scope(default-theme){
  .class { content: 'Will only show in the default theme'; }
}

@include scope(primary-theme){
  .class { content: 'Will only show in the primary theme'; }
}

//  can also be used as "if" function
.class {
  content: scope(default-theme, 'Is default', 'Not default')
}

在您的情况下,在默认变量和主变量中定义 $scope-context

// _default-variables.scss
$scope-context: default-theme !default;

// _primary-variables.scss
$scope-context: primary-theme;

...并将 _scope.scss 添加到 _default-theme.scss

//  _default-theme.scss
@import '_default-variables.scss', '_bootstrap.scss', '_scope.scss';   
于 2017-02-21T10:43:36.080 回答
2

我发现的问题是我错误地假设了 SASS 的工作原理。

当你定义一个变量声明时,它的值在你写它的时候被编译。例如,$my-var: $brand-primary将在处理时分配to的当前值$brand-primary$my-var

这意味着我无法实现我想要的,即在 Bootstrap 顶部包含一个最小变量文件,因为它只会更新变量本身,而不是在 Bootstrap 中引用该变量的任何其他变量。

解决方案

它并不优雅,而是为每个主题复制整个变量文件,并在每个地方根据需要进行调整。

于 2017-02-22T23:20:21.220 回答