在尝试跨 Sass 样式表共享变量和 mixin 时,我遇到了一个令人不安的问题。
如果我曾经@import
包含一个全局样式表——一个包含全局颜色、混合等的样式表——当 Rails 组合清单文件中引用的所有样式表时,它会再次被包含。
或者,如果我的清单文件不包含全局样式表,但清单中的多个文件导入它,则全局样式表仍将包含多次。嘎。
你怎么能解决这个问题?Sass 是否有秘密的包含保护?我做错了什么吗?
在尝试跨 Sass 样式表共享变量和 mixin 时,我遇到了一个令人不安的问题。
如果我曾经@import
包含一个全局样式表——一个包含全局颜色、混合等的样式表——当 Rails 组合清单文件中引用的所有样式表时,它会再次被包含。
或者,如果我的清单文件不包含全局样式表,但清单中的多个文件导入它,则全局样式表仍将包含多次。嘎。
你怎么能解决这个问题?Sass 是否有秘密的包含保护?我做错了什么吗?
我不明白为什么这是您的具体问题的问题。变量和 mixin 声明不应导致生成的 css 文件中的任何选择器或声明块。但是,当您将 mixins 用于多个选择器时,每个此类选择器都会包含相应的声明。这就是 SASS 处理它的方式。
因此,只要它只是变量和 mixin,它们是否在清单文件中多次包含都无关紧要,因为这对编译文件没有影响。在站点节点上,我认为 SASS 强制您显式声明每个文件的依赖项是一种很好的风格。
但是,如果您还希望在单独的文件中继承基文件中的选择器和声明,那么即使在编译的文件中,这些也会被多次包含。知道如何通过配置来防止这种情况仍然很有趣。但是,如果您将每个 sass 文件视为一组没有跨文件继承的封装规则,那么您应该能够按照惯例防止您的问题。
例如,当使用 bootstrap-sass 时,只能将 mixins 和变量定义带入作用域;
@import "bootstrap/variables";
@import "bootstrap/mixins";
你可以通过这样做来解决这个问题:
/*
* 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 截屏视频,这就是他为解决此问题所做的工作。
目前,在 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)的互操作性。我写过,这里
目前无法使用 SASS 动态包含文件。 @import
不能在控制指令(例如@if
)或混合中使用,在导入指令中使用变量是错误的语法,并且没有用于提前结束文件执行的指令(这实际上将允许条件导入)。但是,您可以通过更改样式规则的结构来解决您的问题。
笔记
有一个 SASS 插件可以修改
@import
为只包含一次文件。然而,
如果您的样式有条件地包含在多个文件中,则它们不是“全局”样式。这些样式应该封装在 mixin 中,在“模块”或“库”文件中。主要思想是导入一个这样的文件不会输出任何 css。这样,您可以冗余地导入这些文件,以便您可以在任何需要的地方使用 mixin。
如果您需要使用variables执行此操作,则:
!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;
}
}
有关像这样构建代码的更多良好实践,请查看这篇文章。