【问题标题】:SASS mixin - concatenate/collapse to a single property?SASS mixin - 连接/折叠到单个属性?
【发布时间】:2017-04-14 19:18:30
【问题描述】:

我正在尝试编写一个简单的 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 行中塞满大量参数

【问题讨论】:

    标签: css sass mixins


    【解决方案1】:

    Sass 无法处理您要查找的内容——但您可以使用映射、全局标志和包含包装器来解决它。为什么我会认为以下是反模式。

    Demo on codepen

    注意!以下内容可能需要一些详细说明,但现在我只介绍一些 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
            }        
        }
    }
    

    渲染 Concat

    为了处理值连接,我们为处理全局 concat 标志的渲染混合创建了一个包装混合。

    注意 render-concat 仅用于在 mixins 中设置键/值对——为什么它不使用内容块。

    @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";
    }
    

    如前所述,使用这个要非常小心...你很容易得到意外的输出。

    【讨论】:

    • 感谢您的详细解答。这么简单的功能太复杂了。
    • 有没有其他方法可以解决这个不涉及这种复杂程度的问题?我真正想做的就是多次设置content 属性并追加而不是替换值
    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 2015-04-24
    • 2016-01-26
    • 2015-05-14
    • 2017-01-21
    • 2016-03-25
    • 1970-01-01
    • 2022-07-07
    相关资源
    最近更新 更多