【问题标题】:Restrict mixin values and throw exception when invalid value is provided限制 mixin 值并在提供无效值时抛出异常
【发布时间】:2015-05-31 10:32:47
【问题描述】:

我有以下 Less 混合:

.box-sizing(@value) {
    -webkit-box-sizing: @value;
    -moz-box-sizing: @value;
    box-sizing: @value;
}

我希望只允许值 'border-box' 和 'content-box' 作为参数,否则 Less 引擎应该抛出异常。我怎样才能做到这一点?因为没有这个验证,我可以向 mixin 写入任何值,它会工作,但它也会生成无效的 CSS,没有人会注意到有错误。

【问题讨论】:

    标签: less less-mixins


    【解决方案1】:

    据我所知,没有办法让 Less 编译器针对问题中描述的无效值抛出错误。但是,您可以通过使用 guards feature 使 Less 编译器在提供无效值时根本不产生任何输出。

    在下面的 sn-p 中,只有当两个有效值中的任何一个作为输入传递时才会调用 mixin。如果提供了不同的值,Less 编译器将找不到匹配项,因此不会输出任何内容。

    .box-sizing(@value){
        & when (@value=content-box) , (@value=border-box){ /* comma is the or operator */
            -webkit-box-sizing: @value;
            -moz-box-sizing: @value;
            box-sizing: @value;
        }
    }
    #demo{
        .box-sizing(content-box);
    }
    

    Less 也有一些内置的 type functions 可以与守卫一起使用来检查值是否有效(例如输入是数字还是颜色等)。还有一个 iskeyword 函数,但这些函数都不会检查无效的 CSS 值。


    如果您有大量有效值,则可以使用如下所示的循环功能。在这里,我们从有效值数组中提取每个值,如果输入值与其中一个匹配,则输出属性。如果输入与任何输入值都不匹配,则不输出任何内容(再次)。

    @valid-values: content-box, border-box, padding-box;
    .box-sizing(@value){
        .loop-valid-values(@index) when (@index > 0){
            @valid-value: extract(@valid-values, @index);
            & when (@value= @valid-value){
                -webkit-box-sizing: @value;
                -moz-box-sizing: @value;
                box-sizing: @value;
            }
            .loop-valid-values(@index - 1);
        }
        .loop-valid-values(length(@valid-values));
    }
    #demo{
        .box-sizing(content-box);
    }
    

    绝对不推荐,但如果你坚持让编译器在提供无效值时抛出一些异常,那么你可能会故意在 not-valid-value 中引入错误 部分。

    .box-sizing(@value){
        & when (@value= content-box), (@value= border-box){
            -webkit-box-sizing: @value;
            -moz-box-sizing: @value;
            box-sizing: @value;
        }
        & when not (@value= content-box), (@value= border-box){
            output: @bwahahaha; /* there is no such variable and hence when the input value is not valid, compiler will complain that variable is undefined */
        }
    }
    #demo{
        .box-sizing(conten-box);
    }
    

    【讨论】:

      【解决方案2】:

      您可以将实际的 mixin 实现隐藏在另一个名称下,并且只为 .box-sizing 提供 content-box/border-box 重载:

      // impl.:
      
      .box-sizing(border-box)  {.box-sizing-impl(border-box)}
      .box-sizing(content-box) {.box-sizing-impl(content-box)}
      .box-sizing-impl(@value) {
          -webkit-box-sizing: @value;
          -moz-box-sizing: @value;
          box-sizing: @value;
      }
      
      // usage:
      
      usage {
          .box-sizing(content-box); // OK
          .box-sizing(content-foo); // Error: No matching definition was found for `.box-sizing(content-foo)`
      }
      

      (与守卫不同,"argument pattern matching"(又名重载)不会在不匹配时静默跳过)。

      上面的重复性稍差的变体:

      .box-sizing(@value) {
          .-(@value);
          .-(border-box)  {.ok}
          .-(content-box) {.ok}
      
          .ok() {
              -webkit-box-sizing: @value;
              -moz-box-sizing: @value;
              box-sizing: @value;
          }
      }
      

      这样的错误消息描述性较差:No matching definition was found for '.-(content-foo)',因此您可能会发现使用.box-sizing_ 左右而不是.- 会更好。

      -

      虽然测试每个 mixin 参数并在不合适时抛出错误的想法有点奇怪。 (你要为你编写的每个 mixin 都这样做吗?这很无聊......)你最好将一些 CSS 验证器/lint 放入你的构建链中。

      对于供应商前缀的常见评论:停止为此编写 mixins 并使用 Autoprefixer

      【讨论】:

      • 这很有趣:)
      • 这应该是公认的答案。这太棒了,让我的团队可以很容易地检查工程师是否使用了正确的字体系列和粗细!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 2019-01-14
      • 2013-05-24
      • 1970-01-01
      • 2016-11-07
      相关资源
      最近更新 更多