在Rails 3.1中,是否真的不可能避免包含样式表的重复副本?

时间:2011-06-21 04:47:50

标签: ruby-on-rails sass ruby-on-rails-3.1

尝试在Sass样式表中共享变量和混合时,我遇到了一个令人沮丧的问题。

如果我使用@import来包含一个全局样式表 - 一个包含全局颜色,mixins等的样式表 - 当Rails组合清单文件中引用的所有样式表时,它将再次包含

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

你怎么能绕过这个?萨斯有秘密包容警卫吗?我做错了什么?

4 个答案:

答案 0 :(得分:7)

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

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

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

例如,当使用bootstrap-sass时,只是可以将mixins和变量定义带入范围;

@import "bootstrap/variables";
@import "bootstrap/mixins";

答案 1 :(得分: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或任何其他相关文件。

如果你还没有,请查看Ryan Bates screencast on SASS and sprockets in rails 3.1,这就是他解决这个问题的方法。

答案 2 :(得分: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)的互操作性。我写了这篇文章,here

答案 3 :(得分:0)

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

  

注意

     

a SASS plugin只会修改@import   包含文件一次。然而,

     
      
  1. 您的代码将增加对环境的依赖
  2.   
  3. 我们都会更好地理解样式规则是如何构建的,这样可以避免任何重复的规则。
  4.   
  5. @import可能很快会deprecated。 SASS团队正在计划“large-scale redesign of importing”,因此需要重新导入保护   可能是SASS未来版本的一部分,因为它是popular   请求的功能。
  6.   

解决方案

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

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

  1. 确保在包含mixins之前定义变量,否则它们仅在mixin scope中可用。执行此操作的一种好方法是在vars.sass文件中定义所有默认变量,并将其与导入的模块/库一起导入,以便变量可在全局范围内使用。
  2. 使用mixin中的!default定义变量,因此即使在调用mixin之前也可以覆盖它(如在vars.sass文件中)。
  3. 如果您要确保定义顶级样式而没有严格的包含规则,则可以使用此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;
        }
    }
    

    有关构建此类代码的更多良好做法,请查看this article