Sass 两个先进特性与局限性

发布于 2021-12-28 12:59:22 字数 5287 浏览 1158 评论 0

我真的很喜欢 Sass,并且在我的日常工作中很多时候在使用 Sass。他有很有很有用的功能。但是有很些东西我想做却不能做,他的语法和功能有所限制。今天我想分享一下我在使用Sass的一些发现,同时我也想知道你是否碰到这些限制以及你又是如何绕过他们。

插值 Interpolation

使用CSS预处理器语言的一个主要原因是想使用 Sass 获得一个更好的结构体系。比如说你想写更干净的、高效的和面向对象的CSS。Sass 中的插值(Interpolation)就是重要的一部分。让我们看一下下面的例子:

$properties: (margin, padding);
@mixin set-value($side, $value) {
    @each $prop in $properties {
        #{$prop}-#{$side}: $value;
    }
}
.login-box {
    @include set-value(top, 14px);
}

它可以让变量和属性工作的很完美,上面的代码编译成CSS:

.login-box {
    margin-top: 14px;
    padding-top: 14px;
}

这是Sass插值中一个简单的实例。当你想设置属性值的时候你可以使用字符串插入进来。另一个有用的用法是构建一个选择器。可以这样使用:

@mixin generate-sizes($class, $small, $medium, $big) {
    .#{$class}-small { font-size: $small; }
    .#{$class}-medium { font-size: $medium; }
    .#{$class}-big { font-size: $big; }
}
@include generate-sizes("header-text", 12px, 20px, 40px);

编译出来的CSS:

.header-text-small { font-size: 12px; }
.header-text-medium { font-size: 20px; }
.header-text-big { font-size: 40px; }

一旦你发现这一点,你就会想到超级酷的 mixins,用来生成代码或者生成另一个 mixins。然而,这并不完全是可能的。第一个限制,这可能会很删除用于Sass变量的插值。

$margin-big: 40px;
$margin-medium: 20px;
$margin-small: 12px;
@mixin set-value($size) {
    margin-top: $margin-#{$size};
}
.login-box {
    @include set-value(big);
}

上面的Sass代码编译出来,你会得到下面的信息:

error style.scss (Line 5: Undefined variable: "$margin-".)

所以,#{} 语法并不是随处可用,你也不能在 mixin 中调用:

@mixin updated-status {
    margin-top: 20px;
    background: #F00;
}
$flag: "status";
.navigation {
    @include updated-#{$flag};
}

上面的代码在编译成CSS时同样会报错:

error style.scss (Line 7: Invalid CSS after "...nclude updated-": expected "}", was "#{$flag};")

幸运的是,可以使用 @extend 中使用插值。例如:

%updated-status {
    margin-top: 20px;
    background: #F00;
}
.selected-status {
    font-weight: bold;
}
$flag: "status";
.navigation {
    @extend %updated-#{$flag};
    @extend .selected-#{$flag};
}

上面的Sass代码是可以运行的,因为他给了我们力量,可以动态的插入.class%placeholder。当然他们不能接受像mixin这样的参数,上面的代码编译出来的CSS:

.navigation {
    margin-top: 20px;
    background: #F00;
}
.selected-status, .navigation {
    font-weight: bold;
}

在Sass的社区正在积极讨论插值的局限性,谁又知道呢,也许我们很快将能够使用这些技术也说不定呢。

使用列表作为一个源生成器

如果你在函数或mixin中需要未知数量的参数,这个列表就显得非常的有用。前几天,我遇到了一个问题,我没能解决,至使我不得不改变我的Sass架构。假设我们有下面一段代码:

%margin-reset { margin: 0; }
%padding-reset { padding: 0; }
%size-reset { width: 100%; height: 100%; }
@mixin add-styles($items) {
    @each $item in $items {
        @extend %#{$item};
    }
}
.footer, .header, .login-box {
    @include add-styles((
        margin-reset,
        padding-reset,
        size-reset
    ));
}

编译出来的CSS:

.footer, .header, .login-box {
    margin: 0;
}
.footer, .header, .login-box {
    padding: 0;
}
.footer, .header, .login-box {
    width: 100%;
    height: 100%;
}

到目前为止还好。现在我能够使用@extend扩展我想要的很多%placeholders。但mixins呢?我在想可以用mixin代替%placeholders嵌套吗?第一个问题是,mixins接受参数(如果你有一个不行,就必须考虑重构)。正如你已经看到,主要的想法是通过一个列表,通过后面的元素来读取。每个元素可以是一个mixin或者%placeholders。我发现只有一种方式来区分它们。如果我需要扩展一个占位符,我需要传它的名字,否则我通过另一个列表包含mixin的名称及其参数。例如:

@mixin border-solid($width, $color) {
    border: solid #{$width} #{$color};
}
...
.footer, .header, .login-box {
    @include add-styles((
        margin-reset,
        padding-reset,
        size-reset,
        (border-solid, 3px, #F90)
    ));
}

所以,当我遍历列表中的所有列表项时我必须先检查当前的一个列表。幸运的是有一个函数称为type_of和它返回传递的变量的类型。

@mixin add-styles($items) {
    @each $item in $items {
        @if type_of($item) == "list" {
            // call a mixin
        } @else {
            @extend %#{$item};
        }
    }
}

就像我说的,在本文的第一部分,我们在mixin中不能用插值。像这样的代码实际上是错误的:

@include #{$item}();

据我所了解,目前没有解决方案,和我使用的一个@if...@else

@mixin add-styles($items) {
    @each $item in $items {
        @if type_of($item) == "list" {
            @if nth($item, 1) == "border-solid" {
                @include border-solid(nth($item, 2), nth($item, 3));
            }
        } @else {
            @extend %#{$item};
        }
    }
}

当然我也不喜欢这样的代码。主要是因为我想用它来描述每一个mixin在添加样式。不管怎么样,我是准备使用它,即使这个版本没有工作。一旦我删除%placeholders和只调用(border-solid,3px,#f90),会得到:

Syntax error: Invalid CSS after "%": expected placeholder name, was "3px"

如果你有一个元素的列表它被转换为字符串和我用来检查 @if type_of($item) == "list" 不能正常工作,将会得到一个@else参数和试图@extend一个%placeholder

总结

虽然 Sass 有一定的局限性,但 Sass 仍然是一个美妙的预处理器语言,他带来很多有用的特性。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

想挽留

暂无简介

文章
评论
20374 人气
更多

推荐作者

夢野间

文章 0 评论 0

doggiejohn

文章 0 评论 0

就此别过

文章 0 评论 0

初见终念

文章 0 评论 0

qq_rvKjBH

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文