12

在尝试跨 Sass 样式表共享变量和 mixin 时,我遇到了一个令人不安的问题。

如果我曾经@import包含一个全局样式表——一个包含全局颜色、混合等的样式表——当 Rails 组合清单文件中引用的所有样式表时,它会再次被包含。

或者,如果我的清单文件不包含全局样式表,但清单中的多个文件导入它,则全局样式表仍将包含多次。嘎。

你怎么能解决这个问题?Sass 是否有秘密的包含保护?我做错了什么吗?

4

4 回答 4

7

我不明白为什么这是您的具体问题的问题。变量和 mixin 声明不应导致生成的 css 文件中的任何选择器或声明块。但是,当您将 mixins 用于多个选择器时,每个此类选择器都会包含相应的声明。这就是 SASS 处理它的方式。

因此,只要它只是变量和 mixin,它们是否在清单文件中多次包含都无关紧要,因为这对编译文件没有影响。在站点节点上,我认为 SASS 强制您显式声明每个文件的依赖项是一种很好的风格。

但是,如果您还希望在单独的文件中继承基文件中的选择器和声明,那么即使在编译的文件中,这些也会被多次包含。知道如何通过配置来防止这种情况仍然很有趣。但是,如果您将每个 sass 文件视为一组没有跨文件继承的封装规则,那么您应该能够按照惯例防止您的问题。

例如,当使用 bootstrap-sass 时,只能将 mixins 和变量定义带入作用域;

@import "bootstrap/variables";
@import "bootstrap/mixins";
于 2011-06-22T08:00:27.550 回答
4

你可以通过这样做来解决这个问题:

/* 
 * application.css.scss
 *= require_self
 * ----> Note the missing = require_tree 
*/  

@import "global.css.scss"; // Defines global mixins etc
@import "users.css.scss"; // Uses mixins defined in _global.css.scss

然后不要导入global.css.scss内部users.css.scss或任何其他依赖文件。

如果您还没有,请查看关于 SASS 和 sprockets in rails 3.1 的 Ryan Bates 截屏视频,这就是他为解决此问题所做的工作。

于 2011-06-22T11:19:25.783 回答
1

目前,在 SASS 4 发布之前,我更喜欢将导入行修改为:

@if not-imported("font") { @import "font"; }

当然,您将需要一个名为 not-imported 的函数,如下所示:

$imported-once-files: () !default;

@function not-imported($name) {
  $module_index: index($imported-once-files, $name);
  @if (($module_index == null) or ($module_index == false)) {
    $imported-once-files: append($imported-once-files, $name);
    @return true;
  }
  @return false;
}

这可以正常工作并保持与其他工具(如 StyleDocco)的互操作性。我写过,这里

于 2015-06-11T05:46:14.760 回答
0

目前无法使用 SASS 动态包含文件。 @import不能在控制指令(例如@if)或混合中使用,在导入指令中使用变量是错误的语法,并且没有用于提前结束文件执行的指令(这实际上将允许条件导入)。但是,您可以通过更改样式规则的结构来解决您的问题。

笔记

一个 SASS 插件可以修改@import为只包含一次文件。然而,

  1. 您的代码将增加对环境的依赖
  2. 我们都应该更好地理解样式规则的结构,这将避免任何重复的规则。
  3. @import可能很快就会被弃用。SASS 团队正在计划“大规模重新设计导入”,因此重新导入保护可能会成为 SASS 未来版本的一部分,因为它是受欢迎的 要求功能。

解决方案

如果您的样式有条件地包含在多个文件中,则它们不是“全局”样式。这些样式应该封装在 mixin 中,在“模块”或“库”文件中。主要思想是导入一个这样的文件不会输出任何 css。这样,您可以冗余地导入这些文件,以便您可以在任何需要的地方使用 mixin。

如果您需要使用variables执行此操作,则:

  1. 确保在包含 mixin 之前定义变量,否则它们仅在 mixin范围内可用。这样做的一个好方法是在 vars.sass 文件中定义所有默认变量,并将其与导入的模块/库一起导入,以便变量在全局范围内可用。
  2. 在 mixin 中使用定义变量!default,因此甚至可以在调用 mixin 之前覆盖它(就像在 vars.sass 文件中一样)。

如果您想要确保在没有严格的包含规则的情况下定义顶级样式,则可以使用此 mixin:

$was-defined: () !default;
@mixin define-once($name) {
    @if not index($was-defined, $name) {
        $was-defined: append($was-defined, $name);
        @content;
    }
}

// Example:
@include define-once('body-typography') {
    body {
        font-size: 100%;
        line-height: 2em;
        color: #444;
        font-family: monospace;
    }
}

有关像这样构建代码的更多良好实践,请查看这篇文章

于 2014-01-15T21:28:10.567 回答