SASS mixin - concatenate/collapse 到单个 属性?
SASS mixin - concatenate/collapse to a single property?
我正在尝试编写一个简单的 mixin,它将为传递的 属性 生成一些跨浏览器代码,但是如果您多次调用它,我希望它以某种方式将新值附加到现有 属性规则。
例如:
=foo($foo)
foo: "#{$foo}"
.test
+foo( test 1 )
+foo( test 2 )
将生成
.test {
foo: "test 1";
foo: "test 2";
}
但我试图让它生成的是:
.test {
foo: "test 1, test 2";
}
我知道我可以做 +foo(test 1, test 2)
,但有时我可能有很多参数,并且由于基于缩进的 SASS 语法不允许你将 mixin 参数拆分成多行(遗憾的是),我想要一种使用此 mixin 的更简洁的方法,而无需在 1 行中塞入大量参数
Sass 无法处理您正在寻找的内容——但您可以使用映射、全局标志和包含包装器来解决它。为什么我会认为以下是反模式。
注意!以下内容可能需要详细说明,但现在我只添加一些 SCSS(面向更广泛的受众)——我相信您可以将其转换为 Sass
全局变量
首先,我们创建一组全局变量来保存包含的状态和值。
$render-map:(); // map to hold key value pairs for later render
$render: false; // render flag if true we print out render-map
$concat: false; // concat flag to trigger value concatenation
渲染混合
为了处理跟踪渲染内容的繁琐工作,我们创建了一个多用途渲染混合。该 mixin 可以在其他 mixin 内部使用以设置键值,并在选择器内部使用以呈现独特的属性。我们稍后会创建一个小的 mixin 来处理值连接,因为这是不太常见的用例。
@mixin render($args...){
// no arguments passed and not in the state of rendering
// 1) switch to rendering state
// 2) include content (nested included)
// 3) render render-map content
// 4) before exit disable render state
// 5) empty render-map
@if length($args) == 0 and not $render {
$render: true !global; // 1
@content; // 2
@each $key, $value in $render-map { #{$key}:$value; } // 3
$render: false !global; // 4
$render-map: () !global; // 5
}
// if arguments are passed we loop through keywords to build our render-map
// the keyword key is the same as the passed variable name without the `$`
// e.g. @include render($margin-left: 10px) becomes margin-left: 10px
// 1) get keywords
// 2) loop through keywords
// 3) look for existing render-map values or use empty list
// 4) in case we have a concat flag concatinate render-map value
// 5) in case we don't have a concat flag we overwrite render-map value
// 6) add key value pair to render-map
@else {
$keywords: keywords($args); // 1
@each $key, $value in $keywords { // 2
$map-value: map-get($render-map, $key) or (); // 3
@if $concat { $map-value: if($map-value, append($map-value, $value, comma), $value); } // 4
@else { $map-value: if($value, $value, $map-value); } // 5
$render-map: map-merge($render-map, ($key: $map-value)) !global; // 6
}
}
}
渲染连接
为了处理值连接,我们为处理全局连接标志的渲染混合创建了一个包装器混合。
注意 render-concat 仅用于在 mixin 中设置 key/value 对——为什么它不采用内容块。
@mixin render-concat($args...){
$concat: true !global; // set global concat flag for render mixin
@include render($args...); // pass args on to the render mixin
$concat: false !global; // reset global concat flag
}
用法
@mixin foo($value){
// add the passed value to the `foo` key ($ is stripped) of the render-map.
@include render-concat($foo: $value);
}
.test {
// in order to render our render-map content we wrap our includes
// inside a @include render (without any arguments).
// note the quoted strings to prevent sass from thinking we are passing lists
@include render {
@include foo('test 1');
@include foo('test 2');
@include foo('test 3');
}
}
输出
.test {
foo: "test 1", "test 2", "test 3";
}
如前所述,使用时要非常小心......你很容易得到意想不到的输出。
我正在尝试编写一个简单的 mixin,它将为传递的 属性 生成一些跨浏览器代码,但是如果您多次调用它,我希望它以某种方式将新值附加到现有 属性规则。
例如:
=foo($foo)
foo: "#{$foo}"
.test
+foo( test 1 )
+foo( test 2 )
将生成
.test {
foo: "test 1";
foo: "test 2";
}
但我试图让它生成的是:
.test {
foo: "test 1, test 2";
}
我知道我可以做 +foo(test 1, test 2)
,但有时我可能有很多参数,并且由于基于缩进的 SASS 语法不允许你将 mixin 参数拆分成多行(遗憾的是),我想要一种使用此 mixin 的更简洁的方法,而无需在 1 行中塞入大量参数
Sass 无法处理您正在寻找的内容——但您可以使用映射、全局标志和包含包装器来解决它。为什么我会认为以下是反模式。
注意!以下内容可能需要详细说明,但现在我只添加一些 SCSS(面向更广泛的受众)——我相信您可以将其转换为 Sass
全局变量
首先,我们创建一组全局变量来保存包含的状态和值。
$render-map:(); // map to hold key value pairs for later render
$render: false; // render flag if true we print out render-map
$concat: false; // concat flag to trigger value concatenation
渲染混合
为了处理跟踪渲染内容的繁琐工作,我们创建了一个多用途渲染混合。该 mixin 可以在其他 mixin 内部使用以设置键值,并在选择器内部使用以呈现独特的属性。我们稍后会创建一个小的 mixin 来处理值连接,因为这是不太常见的用例。
@mixin render($args...){
// no arguments passed and not in the state of rendering
// 1) switch to rendering state
// 2) include content (nested included)
// 3) render render-map content
// 4) before exit disable render state
// 5) empty render-map
@if length($args) == 0 and not $render {
$render: true !global; // 1
@content; // 2
@each $key, $value in $render-map { #{$key}:$value; } // 3
$render: false !global; // 4
$render-map: () !global; // 5
}
// if arguments are passed we loop through keywords to build our render-map
// the keyword key is the same as the passed variable name without the `$`
// e.g. @include render($margin-left: 10px) becomes margin-left: 10px
// 1) get keywords
// 2) loop through keywords
// 3) look for existing render-map values or use empty list
// 4) in case we have a concat flag concatinate render-map value
// 5) in case we don't have a concat flag we overwrite render-map value
// 6) add key value pair to render-map
@else {
$keywords: keywords($args); // 1
@each $key, $value in $keywords { // 2
$map-value: map-get($render-map, $key) or (); // 3
@if $concat { $map-value: if($map-value, append($map-value, $value, comma), $value); } // 4
@else { $map-value: if($value, $value, $map-value); } // 5
$render-map: map-merge($render-map, ($key: $map-value)) !global; // 6
}
}
}
渲染连接
为了处理值连接,我们为处理全局连接标志的渲染混合创建了一个包装器混合。
注意 render-concat 仅用于在 mixin 中设置 key/value 对——为什么它不采用内容块。
@mixin render-concat($args...){
$concat: true !global; // set global concat flag for render mixin
@include render($args...); // pass args on to the render mixin
$concat: false !global; // reset global concat flag
}
用法
@mixin foo($value){
// add the passed value to the `foo` key ($ is stripped) of the render-map.
@include render-concat($foo: $value);
}
.test {
// in order to render our render-map content we wrap our includes
// inside a @include render (without any arguments).
// note the quoted strings to prevent sass from thinking we are passing lists
@include render {
@include foo('test 1');
@include foo('test 2');
@include foo('test 3');
}
}
输出
.test {
foo: "test 1", "test 2", "test 3";
}
如前所述,使用时要非常小心......你很容易得到意想不到的输出。