在SASS中动态调用mixin / function来干掉冗余代码块 - 某种eval()功能?

时间:2016-03-01 19:25:18

标签: css ruby sass metaprogramming

我的Sass代码中有很多mixins用于生成媒体查询和非媒体查询属性:

@mixin create-responsive-font-size($breakpoint, $font-size) {
  $breakpoints-map: map-deep-get($config, breakpoints);

  // TODO: abstract into reusable function
  @if $breakpoint == none {
    @include create-font-size($font-size);
  }
  @else if map-has-key($breakpoints-map, $breakpoint) {
    $mapped-breakpoint: map-get($breakpoints-map, $breakpoint);

    @media screen and (min-width: $mapped-breakpoint) {
      @include create-font-size($font-size);
    }
  }
}

@mixin create-font-size($font-size) {
  // irrelevant other code here
  ...

  font-size: $px-font-size;
  font-size: $rem-font-size;
}

我真的想干掉那个前mixin以抽象@if/@else部分,因为我有许多使用完全相同逻辑的mixin。但是,块中的逻辑并不总是相同的 - 有时会调用另一个mixin(如第一个示例中所示),有时会直接设置属性,如下所示:

@mixin create-responsive-line-height($breakpoint, $line-height) {
  $breakpoints-map: map-deep-get($config, breakpoints);

  $line-height: $line-height !default;

  // TODO: abstract into reusable function
  @if $breakpoint == none {
    line-height: $line-height;
  }
  @else if map-has-key($breakpoints-map, $breakpoint) {
    $mapped-breakpoint: map-get($breakpoints-map, $breakpoint);

    @media screen and (min-width: $mapped-breakpoint) {
      line-height: $line-height;
    }
  }
}

现在,以这样的方式抽象@if/@else以便我可以动态地将命令传递给新的帮助程序mixin并通过取消引用并运行某种形式的eval来执行它是很酷的。 ,就像Javascript中的那样:

@mixin invoke-dynamic($breakpoint, $command) {
  $breakpoints-map: map-deep-get($config, breakpoints);

  @if $breakpoint == none {
    call(unquote($command));
  }
  @else if map-has-key($breakpoints-map, $breakpoint) {
    $mapped-breakpoint: map-get($breakpoints-map, $breakpoint);

    @media screen and (min-width: $mapped-breakpoint) {
      call(unquote($command));
    }
  }
}

假设我们重写了之前的两个mixin示例,那么这将被调用:

@mixin create-responsive-font-size($breakpoint, $font-size) {
  @include invoke-dynamic($breakpoint, "@include create-font-size($font-size);");
}

@mixin create-responsive-line-height($breakpoint, $line-height) {
  @include invoke-dynamic($breakpoint, "line-height: $line-height;");
}

即使我必须将每个子调用包装在另一个mixin中以避免直接属性设置(与line-height示例一样),我也会考虑类似的功能。

这似乎是Sass的相当高级的用法,我找不到任何实现这样的资源。此外,即使尝试动态调用mixins,似乎也存在一些问题,使我的尝试更加无效。

对于像这样的方法,对方法或代码重组完全接受任何建议!

0 个答案:

没有答案