基于Element-ui组件库

Vue组件库必备 Sass(Dart) 知识

2022-08-14  本文已影响0人  WebJeffery

前言

Sass 有三个版本 Dart SasslibsassRuby Sass

Sass 官方团队在2020年10月也正式宣布 Libsass 将弃用,以及基于它的 Node SassSassC,并且建议用户使用 Dart Sass,主要有以下几点说明:

为什么使用 Dart Sass

目前 Dart Sass 已经作为 Sass 最新的版本了,当执行 npm install sass -D 默认使用的是 Dart Sass 包,vue-cliVite 脚手架默认也是使用最新版本 Dart sass,而且不需要安装 node-sass【之前安装 node-sass 经常失败】

另外,element-plus 组件库也是使用 dart dass 模块的 sass:map@use 重构了所有的 SCSS 变量,解决了由 @import 造成的重复输出问题。

所以,为了获得 sass 提供更多更强大的功能,强烈推荐使用 dart sass

安装使用

如果之前安装了 node-sass,可以先卸载

npm uninstall node-sass

安装 dart-sass

npm install sass sass-loader@^10.1.1 -D

注意:之前安装 sass-loader 版本是 13.0+,版本过高导致报错,提示 TypeError: this.getOptions is not a function,退回 10.+ 可以运行成功

如果项目之前用到 /deep/ 需要替换为 ::v-deep,全局搜索 /deep/ , 将项目里的 /deep/ 替换为 ::v-deep

SCSS变量

scss 变量命名规则

$color:#F00;
p {
    color: $color;
}

编译为

p {
    color: #F00;
}

SCSS 变量有两种作用域:全局变量域局部变量域

$color: red;
.container {
    $height: 500px;
    $font-size: 16px !global; // 全局变量,外部可以使用
    font-size: $font-size;
    color: $color;
    height: $height;
}
.footer {
    /**$font-size使用!global 申明成全局变量了*/
    font-size: $font-size; 
    /**
    * Error: Undefined variable. 
    * $height是.container下的局部变量,无法在.footer下面编译
    */
    height:$height;
}

编译 css

.container {
    font-size: 16px;
    color: red;
    height: 500px;
}

.footer {
     /**$font-size使用!global 申明成全局变量了*/
    font-size: 16px;
}

CSS 变量

Sass 默认支持css变量,通过 scss 变量 和 css 变量管理可以很容易实现换肤,element-plus 是这样实现的

css 变量 声明一个自定义属性,属性名需要以两个减号(--)开始,定义变量 --变量名:变量值 例如: --main-color: black;,由 var() 函数来获取值,例如 color: var(--main-color)

:root {
    --main-color: #F00;
}
p {
    color: var(--main-color);
}

:root 是在 HTML 文档的任何地方都可以访问到它

注意: 自定义属性名是大小写敏感的,--my-color--My-color 会被认为是两个不同的自定义属性

通过 JavaScript 获取或者修改 CSS 变量和操作普通 CSS 属性是一样

// 获取一个 Dom 节点上的 CSS 变量
element.style.getPropertyValue("--my-var");

// 获取任意 Dom 节点上的 CSS 变量
getComputedStyle(element).getPropertyValue("--my-var");

// 修改一个 Dom 节点上的 CSS 变量
element.style.setProperty("--my-var", jsVar + 4);

SCSS 数据类型

// 数字
$layer-index: 10;
$border-width: 3px;

// 字符串
$font-weight: bold;

// 数组
$font-base-family: "Open Sans", Helvetica, Sans-Serif;
$block-base-padding: 6px 10px 6px 10px;

// 颜色
$top-bg-color: rgba(255, 147, 29, 0.6);

// 布尔值
$blank-mode: true;

// null
$var: null;

// maps 值
$fonts: (
  serif: "Helvetica Neue",
  monospace: "Consolas",
);

.container {
  // 内部变量
  font-family: $font-base-family;
  font-size: $font-size;
  padding: $block-base-padding;

  @if $blank-mode {
    background-color: #000;
  } @else {
    background-color: #fff;
  }

  content: type-of($var);
  content: length($var);
  color: $top-bg-color;
}

// 如果列表中包含空值,则生成的CSS中将忽略该空值。
.wrap {
  font: 18px $font-weight map-get($fonts, "sans");
}

!default

可以在变量的结尾添加 !default 来给变量设置默认值,有点类似 Javascript 的逻辑运算符 let content=value || "default value" 。注意,变量是 null 时将视为未被 !default 赋值

// 如果$content之前没使用 !default,没办法赋值覆盖
$content: "First content";
$content: "Second content" !default;
#main {
    content: $content;
}

编译成 css

#main {
  content: "First content";
}

插值语句

通过 #{} 插值语句可以在选择器、属性名、注释中使用变量,使用 #{} 插值语句将变量包裹起来即可,和 js 中的 模板字符串 很像

$font-size: 12px;
$line-height: 30px;
$class-name: danger;
$attr: color;
$author: "福大命大";

p {
    font: #{$font-size}/#{$line-height} Arial Helvetica, sans-serif;
}

/* 
* 这是文件的说明部分
* @author: #{$author}
*/

a.#{$class-name} {
    border-#{$attr}: #f00;
}

编译为css

p {
    font: 12px/30px Arial Helvetica, sans-serif;
}

/* 
* 这是文件的说明部分
* @author: 福大命大
*/
a.danger {
    border-color: #f00;
}

条件语句 @if

@if 语法和 js 类似,基本格式是 @if...@else if...@else

$theme:3;
.container {
    @if $theme >= 5 {
        background-color: red;
    }
    @else {
        background-color: blue;
    }
}

编译为 css

.container {
    background-color: blue;
}

@for 循环

for 在条件范围内重复操作,这个指令包含两种格式:

两者区别在于 throughto 的含义

$var 可以是任何变量,比如 $istartend 必须是整数值。

@for $i from 1 to 3 {
  #loading span:nth-child(#{$i}) {
      width: 20 * ($i - 1) + px;
  }
}

编译为 css

#loading span:nth-child(1) {
    width: 0px;
}

#loading span:nth-child(2) {
    width: 20px;
}

如果把 to 换成 through

#loading span:nth-child(1) {
    width: 0px;
}

#loading span:nth-child(2) {
    width: 20px;
}

#loading span:nth-child(3) {
    width: 40px;
}

@each 循环

@each 指令的格式是 @each $var in $list , $var 可以是任何变量名,比如 $length 或者 $name,而 $list 是一连串的值,也就是值列表

$color-list:red green blue turquoise darkmagenta;
@each $color in $color-list {
    $index: index($color-list, $color);
    .p#{$index - 1} {
        background-color: $color;
    }
}

编译为 css

.p0 {
    background-color: red;
}

.p1 {
    background-color: green;
}

.p2 {
    background-color: blue;
}

.p3 {
    background-color: turquoise;
}

.p4 {
    background-color: darkmagenta;
}

@while 循环

@while 指令循环输出直到表达式返回结果为 false。这样可以实现比 @for 更复杂的循环。比如,可以借此生成栅格化布局

$column:12;
@while $column>0 {
   .col-sm-#{$column} {
      width: $column / 12 * 100%;
   }
    $column:$column - 1;
}

编译为 css

.col-sm-12 {
    width: 100%;
}

.col-sm-11 {
    width: 91.6666666667%;
}

.col-sm-10 {
    width: 83.3333333333%;
}

.col-sm-9 {
    width: 75%;
}

.col-sm-8 {
    width: 66.6666666667%;
}

.col-sm-7 {
    width: 58.3333333333%;
}

.col-sm-6 {
    width: 50%;
}

.col-sm-5 {
    width: 41.6666666667%;
}

.col-sm-4 {
    width: 33.3333333333%;
}

.col-sm-3 {
    width: 25%;
}

.col-sm-2 {
    width: 16.6666666667%;
}

.col-sm-1 {
    width: 8.3333333333%;
}

@import

scss 拓展了 @import 的功能,允许其导入 scss或 sass文件。被导入的文件将合并编译到同一个 css 文件中,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。

common.scss

$color:red;

index.scss

@import "common.scss";
.container {
    border-color: $color;
}

编译为 css

.container {
  border-color: red;
}

以下情况下,@import 仅作为普通的 css 语句,不会导入 scss 文件:

@import "common.css";
@import url(common);
@import "http://xxx.com/xxx";
@import 'landscape' screen and (orientation:landscape);

scss 允许同时导入多个文件,例如同时导入 a.scssb.scss 两个文件,不用再单独写个 import 引入

@import "a", "b";

@Partials

如果需要导入 scss 或者 sass 文件,但又不希望将其编译为 css,只需要在文件名前添加下划线,这样会告诉 scss 不要编译这些文件。
注意:

_common.scss

$color:red;

index.scss

@import "common.scss";
.container {
    border-color: $color;
}

编译为

.container {
  border-color: red;
}

_common.scss 文件不会编译成 _common.css 文件,Partials 主要是用来定义公共样式的,专门用于被其他的 scss 文件 import 进行使用的

@mixin

混合指令(Mixin)用于定义可重复使用的样式。混合指令可以包含所有的css规则,绝大部分 scss 规则,甚至可以通过参数功能引入变量,输出多样化的样式;

@mixin@include 配合使用

// 定义一个区块基本的样式
@mixin block {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
}
// 使用混入 
.container {
    .block {
        @include block;
    }
}

编译为 css

.container .block {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
}

@mixin 可以定义多个参数和默认值

// 定义块元素内边距,参数指定默认值
@mixin block-padding($top:0, $right:0, $bottom:0, $left:0) {
    padding-top: $top;
    padding-right: $right;
    padding-bottom: $bottom;
    padding-left: $left;
}

// 可指定参数赋值
.container {
    /** 不带参数 */
    @include block-padding;
    /** 按顺序指定参数值 */
    @include block-padding(10px,20px);
    /** 给指定参数指定值 */
    @include block-padding($left: 10px, $top: 20px)
}

编译 CSS

.container {
    /** 不带参数 */
    padding-top: 0;
    padding-right: 0;
    padding-bottom: 0;
    padding-left: 0;
    /** 按顺序指定参数值 */
    padding-top: 10px;
    padding-right: 20px;
    padding-bottom: 0;
    padding-left: 0;
    /** 给指定参数指定值 */
    padding-top: 20px;
    padding-right: 0;
    padding-bottom: 0;
    padding-left: 10px;
}

可变参数:使用 ... 处理参数不固定的情况,类似于js中的函数的剩余参数

@mixin linear-gradient($direction, $gradients...) {
    background-color: nth($gradients, 1);
    background-image: linear-gradient($direction, $gradients);
}

.table-data {
    @include linear-gradient(to right, #F00, orange, yellow);
}

编译为

.table-data {
    background-color: #F00;
    background-image: linear-gradient(to right, #F00, orange, yellow);
}

总结

@function 函数

@function 用于封装复杂的操作,可以很容易地以一种可读的方式抽象出通用公式和行为,函数提供返回值,常用来做计算方面的工作

@function 参数默认值

//change-color和hue是内置方法
//hue 返回$color的颜色为0到360度之间的一个数字。
//change-color 用于设置颜色的属性
@function invert($color, $amount: 100%) {
    //@error hue($color); 调试 210deg
    $inverse: change-color($color, $hue: hue($color) + 180);
    @return mix($inverse, $color, $amount);
}

$primary-color: #036;
.header {
    background-color: invert($primary-color, 80%);
}

编译 CSS

.header {
    background-color: #523314;
}

可变参数 看作 js function 的 rest 参数

@function sum($numbers...) {
    $sum: 0;
    @each $number in $numbers {
        $sum: $sum + $number;
    }
    @return $sum;
}

$widths: 50px, 30px, 100px;
.micro {
    width: sum($widths...);
}

编译为 CSS

.micro {
    width: 180px;
}

@return 只允许在 @function 内使用,和 js 一样,遇到 return 就会返回

总结

@extend继承

elementUIel-button 组件为例,可以使用 @extend 继承已经存在的样式,使用逗号选择器。

// # id选择器一样的
.button {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    @extend .button;
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    @extend .button;
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

编译成 css

.button, .btn-danger, .btn-default {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

占位符选择器

占位符选择器 %,与常用的 idclass 选择器写法相似,只是 #. 替换成了 %,占位符选择器必须通过 @extend 指令调用

.button %base {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}
        
.btn-default {
    @extend %base;
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    @extend %base;
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

效果和上面的类选择器一样,但是,他有个有优点,占位符选择器% 所属的样式未使用时,不会被编译到 css 文件中

.button .btn-danger, .button .btn-default {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    background-image: none;
    border: 1px solid transparent;
    padding: 6px 12px;
    font-size: 14px;
    line-height: 1.42857143;
    border-radius: 4px;
    user-select: none;
}

.btn-default {
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}

.btn-danger {
    color: #fff;
    background-color: #d9534f;
    border-color: #d43f3a;
}

@use

存在兼容性问题,仅在 Dart Sass 1.23.0 以上有效,官方文档有兼容性介绍

css 真正意义上的模块化,可以从其它 scss 样式表中加载 mixinfunction 和变量,并将来自多个样式表的 css 组合在一起。scss 还提供了很多内置模块,我们可以通过 @use 使用,官方也推荐使用 @use 替换 @import,后续会废弃 @import

@import缺点

@use 使用默认带有命名空间,也可以重命名空间

src/_corners.scss

$radius: 3px;
@mixin rounded {
    border-radius: $radius;
}

index.scss

@use "src/corners"; // 默认命名空间 corners
// @use "src/corners" as c; // 重命名空间
.button {
    @include corners.rounded;
    padding: 5px + corners.$radius;
    // padding: 5px + c.$radius; // 重命名 c 引用
}

as * 让模块处于全局命名空间,不需要带上命名空间就可以直接使用

$radius: 3px;
@mixin rounded {
    border-radius: $radius;
}

使用

@use "src/corners" as *;

.button {
    @include rounded;
    padding: 5px + $radius;
}

私有模块

变量使用 - 开头,@use 不会引入这个变量

$-radius: 3px;

@mixin rounded {
    border-radius: $-radius;
}

index.scss

@use "src/corners";

.button {
    @include corners.rounded;
    // Error: Private members can't be accessed from outside their modules
    padding: 5px + corners.$-radius;
}

@forward

@forward 可以看作是转发,在当前模块引入另一个模块的所有变量、mixins 和函数,直接向外暴露 API,不会在当前模块增加代码,不同于 @use@forward 不能给变量添加命名空间

例如在 bootstrap.css 引入 functionsvariablesmixins 文件,不能直接在 bootstrap.scss 文件中使用这些引入的模块。而是需要在另一个文件中引入 @use bootstrap 模块,再去使用这些方法

/* bootstrap.scss */
@forward"functions";
@forward"variables";
@forward"mixins";

@forward 通过控制 showhide 显示或隐藏模块中的某些变量

a.scss

@mixin rounded {
    border-radius: 100px;
}
footer {
    height: 1px;
}

b.scss

$radius: 3px;

c.scss
```scss
@forward "a" show rounded;
@forward "b" hide $radius;

index.scss

@import "c.scss";

.button {
    @include rounded;
    padding: $radius;
}
// Error: Undefined variable. padding: $radius;

@at-root

@at-root 用来跳出嵌套,在多级嵌套时比较常用,包含 withoutwith

//没有跳出
.parent-1 {
    color:#f00;
    .child {
        width:100px;
    }
}

//单个选择器跳出
.parent-2 {
    color:#f00;
    @at-root .child {
        width:200px;
    }
}

//多个选择器跳出
.parent-3 {
    background:#f00;
    @at-root {
        .child1 {
            width:300px;
        }
        .child2 {
            width:400px;
        }
    }
}

编译为

.parent-1 {
    color: #f00;
}
.parent-1 .child {
    width: 100px;
}

.parent-2 {
    color: #f00;
}
.child {
    width: 200px;
}

.parent-3 {
    background: #f00;
}
.child1 {
    width: 300px;
}

.child2 {
    width: 400px;
}

@without和with

默认 @at-root 只会跳出选择器嵌套,而不能跳出 @media@support,如果要跳出这两种,则需使用@at-root (without: media)@at-root (without: support)@at-root 的关键词有四个

默认的 @at-root@at-root (without:rule)

/*跳出父级元素嵌套*/
@media print {
    .parent1{
        color:#f00;
        @at-root .child1 {
            width:200px;
        }
    }
}

/*跳出media嵌套,父级有效*/
@media print {
    .parent2{
        color:#f00;
        @at-root (without: media) {
            .child2 {
                width:200px;
            }
        }
    }
}

/*跳出media和父级*/
@media print {
    .parent3{
        color:#f00;
        @at-root (without: all) {
            .child3 {
                width:200px;
            }
        }
    }
}

编译成

/*跳出父级元素嵌套*/
@media print {
    .parent1 {
        color: #f00;
    }
    .child1 {
        width: 200px;
    }
}
/*跳出media嵌套,父级有效*/
@media print {
    .parent2 {
        color: #f00;
    }
}
.parent2 .child2 {
    width: 200px;
}
/*跳出media和父级*/
@media print {
    .parent3 {
        color: #f00;
    }
}
.child3 {
    width: 200px;
}

@at-root与 & 配合使用

.child{
    @at-root .parent &{
        color:#f00;
    }
}

编译为

.parent .child {
    color: #f00;
}

SCSS 内置拓展

scss内置扩展分为 color, list, map, math, meta, selector, string 等,扩展也就是 scss 内置的一些 function,相当于 JS 内置方法

内置函数可以使用 @use 模块化引入,也可以直接使用他提供的全局函数名调用,以下两种方式是一样的。

@use 'sass:list';
p {
    color: nth($list: red blue green, $n: 2); // blue
    color: list.nth($list: red blue green, $n: 2); // blue
}

String 字符串函数

scss 有许多处理字符串的函数

quote(hello) //"hello"
unquote("hello") //hello
str-index(abcd, a) // 1 
str-index(abcd, ab) // 1 
str-index(abcd, X) // null
str-length("hello") //5
str-insert("Hello world!", " xiaoming", 6) //"Hello xiaoming world!"
str-slice("abcd", 2, 3)   => "bc" 
str-slice("abcd", 2)      => "bcd" 
str-slice("abcd", -3, -2) => "bc" 
str-slice("abcd", 2, -2)  => "bc"

其他

事例代码

p {
    &:after {
        content: quote(这是里面的内容);
    }
    background-color: unquote($string: "#F00");
    z-index:str-length("scss学习");
}

编译结果

p {
    background-color: #F00;
    z-index: 6;
}
p:after {
    content: "这是里面的内容";
}

Math 数学函数

Math 数值函数处理数值计算

abs(13) // 13 
abs(-13) // 13
comparable(15px, 10px) // true 
comparable(20mm, 1cm) // true 
comparable(35px, 2em) // false
ceil(13.24) //14
floor(15.84) // 15
max(5, 7, 9, 0, -3, -7) // 9
min(7, 2, 0, -2, -7) // -7
percentage(1.2) // 120
random() // 0.2783
random(10) // 4
round(15.20) // 15 round(15.80) // 16
@debug math.div(1, 2); // 0.5
@debug math.div(100px, 5px); // 20
@debug math.div(100px, 5); // 20px
@debug math.div(100px, 5s); // 20px/s
@debug math.percentage(0.2); // 20%

事例代码

p {
    z-index: abs(-15); // 15
    z-index: ceil(5.8); //6
    z-index: max(5, 1, 6, 8, 3); //8
    opacity: random(); // 随机 0-1
}

编译为

p {
    z-index: 15;
    z-index: 6;
    z-index: max(5, 1, 6, 8, 3);
    opacity: 0.8636254167;
}

List 列表函数

List 特点

List 方法

append((a b c), d) // a b c d 
append((a b c), (d), comma) // a, b, c, d
index(a b c, b) // 2 
index(a b c, f) // null
is-bracketed([a b c]) // true 
is-bracketed(a b c) // false
list-separator(a b c) // "space"
list-separator(a, b, c) // "comma"
join(a b c, d e f) // a b c d e f 
join((a b c), (d e f), comma) // a, b, c, d, e, f 
join(a b c, d e f, $bracketed: true) // [a b c d e f]
length(a b c) // 3
set-nth(a b c, 2, x) // a x c
nth(a b c, 3) // c
zip(1px 2px 3px, solid dashed dotted, red green blue) 
// 1px solid red, 2px dashed green, 3px dotted blue

事例代码

p {
    z-index: length(12px); //1
    z-index: length(12px 5px 8px); //3
    z-index: index(a b c d, c); //3
    padding: append(10px 20px, 30px); // 10px 20px 30px
    color: nth($list: red blue green, $n: 2); // blue
    @debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long
}

编译结果

p {
    z-index: 1;
    z-index: 3;
    z-index: 3;
    padding: 10px 20px 30px;
    color: blue;
}

Map(映射) 函数

Sass Map 是不可变的,因此在处理 Map 对象时,返回的是一个新的 Map 对象,而不是在原有的 Map 对象上进行修改。

Map(映射)对象是以一对或多对的 key/value 来表示

$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
map-get($font-sizes, "small") // 12px
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
map-has-key($font-sizes, "big") // false
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
map-keys($font-sizes) // "small", "normal, "large"
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
map-values($font-sizes) // 12px, 18px, 24px
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
$font-sizes2: ("x-large": 30px, "xx-large": 36px)

map-merge($font-sizes, $font-sizes2) 
//"small": 12px, "normal": 18px, "large": 24px, "x-large": 30px, "xx-large": 36px
$helvetica-light: (
  "weights": (
    "lightest": 100,
    "light": 300
  )
);
$helvetica-heavy: (
  "weights": (
    "medium": 500,
    "bold": 700
  )
);

@debug map.deep-merge($helvetica-light, $helvetica-heavy);
// (
//   "weights": (
//     "lightest": 100,
//     "light": 300,
//     "medium": 500,
//     "bold": 700
//   )
// )
@debug map.merge($helvetica-light, $helvetica-heavy);
// (
//   "weights": (
//     "medium: 500,
//     "bold": 700
//   )
// )
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px) 
map-remove($font-sizes, "small") // ("normal": 18px, "large": 24px) 
map-remove($font-sizes, "small", "large") // ("normal": 18px)
$fonts: (
  "Helvetica": (
    "weights": (
      "regular": 400,
      "medium": 500,
      "bold": 700
    )
  )
);

@debug map.deep-remove($fonts, "Helvetica", "weights", "regular");
// (
//   "Helvetica": (
//     "weights: (
//       "medium": 500,
//       "bold": 700
//     )
//   )
// )
$fonts: (
  "Helvetica": (
    "weights": (
      "regular": 400,
      "medium": 500,
      "bold": 700
    )
  )
);

@debug map.set($fonts, "Helvetica", "weights", "regular", 300);
// (
//   "Helvetica": (
//     "weights": (
//       "regular": 300,
//       "medium": 500,
//       "bold": 700
//     )
//   )
// )

事例代码

@use 'sass:map';

// 创建Map,类似于对象
$map: (
  key: value,
  nextkey: nextvalue
);

// 使用
.element:before {
  content: map-get($map, key);
}

上面编译输出后的结果如下:

.element:before {
  content: value
}

Map@each 应用

/* 定义一个sass map名称为$icons */
$icons: (
  checkmark: a,
  plus: b,
  minus: c
);

/* 遍历map的所有key,创建各自的类 */
@each $name, $value in $icons {
  .icon--#{$name} {
    content: $value;
  }
}

编译结果


/* 遍历map的所有key,创建各自的类 */
.icon--checkmark {
  content: "a";
}

.icon--plus {
  content: "b";
}

.icon--minus {
  content: "c";
}

@each 遍历嵌套 map 多个值

// _m-buttons.scss
$buttons: (
  error: (#d82d2d, #666),
  success: (#52bf4a, #fff),
  warning: (#c23435, #fff)
);

.m-button {
  display: inling-block;
  padding: .5em;
  background: #ccc;
  color: #666;

  @each $name, $colors in $buttons {
    $bgcolor: nth($colors, 1);
    $fontcolor: nth($colors, 2);

    &--#{$name} {
      background-color: $bgcolor;
      color: $fontcolor;
    }
  }
}

编译结果

.m-button {
  display: inline-block;
  padding: .5em;
  background: #ccc;
  color: #666;
}

.m-button--error {
  background-color: #d82d2d;
  color: #666;
}

.m-button--success {
  background-color: #52bf4a;
  color: #fff;
}

.m-button--warning {
  background-color: #c23435;
  color: #fff;
}

selector 选择器函数

selector 相关函数可对选择 css 进行一些相应的操作

is-superselector("div", "div.myInput") // true 
is-superselector("div.myInput", "div") // false 
is-superselector("div", "div") // true
selector-append("div", ".myInput") // div.myInput 
selector-append(".warning", "__a") 结果: .warning__a
selector-nest("ul", "li") // ul li 
selector-nest(".warning", "alert", "div") // .warning div, alert div
selector-parse("h1 .myInput .warning") // ('h1' '.myInput' '.warning')
selector-replace("p.warning", "p", "div") // div.warning
selector-unify("myInput", ".disabled") // myInput.disabled 
selector-unify("p", "h1") // null
simple-selectors("div.myInput") // div, .myInput 
simple-selectors("div.myInput:before") // div, .myInput, :before

事例代码

@use 'sass:selector';

@debug selector.is-superselector("a", "a"); // true

// 可以直接使用@forward下的前缀
@debug selector-append("a", ".disabled"); // a.disabled
@debug selector-extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled

.header {
    content: selector-append(".a", ".b", ".c") + '';
    content: selector-unify("a", ".disabled") + '';
}

meta

meta 提供一个 mixin 和一些原子级别的 function

meta.load-css

meta.load-css($url,$with:())$urlcss样式全部包含进来。注意,$url引入的函数,变量和mixinmeta.load-css()后的scss中并不能用,它只会返回编译后的css代码。它的第二个参数可以修改使用了!default的变量

src/corners

$border-contrast: false !default;

code {
    background-color: #6b717f;
    color: #d2e1dd;
    @if $border-contrast {
        border-color: #dadbdf;
    }
}

index.scss

@use "sass:meta";

body.dark {
    @include meta.load-css("src/corners", $with: ("border-contrast": true));
}

编译为

body.dark code {
    background-color: #6b717f;
    color: #d2e1dd;
    border-color: #dadbdf;
}

相关 function

@use "sass:meta";

@debug meta.calc-args(calc(100px + 10%)); // unquote("100px + 10%")
@debug meta.calc-args(clamp(50px, var(--width), 1000px)); // 50px, unquote("var(--width)"), 1000px

@debug meta.calc-name(calc(100px + 10%)); // "calc"
@debug meta.calc-name(clamp(50px, var(--width), 1000px)); // "clamp"

color 颜色函数

scss包含很多操作颜色的函数。

rgb(0, 255, 255);
rgba(0, 255, 255, 0.3);
hsl(120, 100%, 50%); // 绿色 
hsl(120, 100%, 75%); // 浅绿色 
hsl(120, 100%, 25%); // dark green 
hsl(120, 60%, 70%); // 柔和的绿色 
hsl(120, 100%, 50%, 0.3); // 绿色带有透明度 
hsl(120, 100%, 75%, 0.3); // 浅绿色带有透明度
grayscale(#7fffd4); // #c6c6c6
complement(#7fffd4); // #ff7faa
invert(white); // black
red(#7fffd4); // 127 
red(red); // 255
green(#7fffd4); // 255 
green(blue); // 0
blue(#7fffd4); // 212 
blue(blue); // 255
hue(#7fffd4); // 160deg
saturation(#7fffd4); // 100%
lightness(#7fffd4); // 74.9%
alpha(#7fffd4); // 1
opacity(rgba(127, 255, 212, 0.5); // 0.5

weight 参数必须是 0% 到 100%。默认 weight 为 50%,表明颜色各取 50% color1 和 color2 的色值相加。如果 weight 为 25%,那表明颜色为 25% color1 和 75% color2 的色值相加

adjust-hue(#7fffd4, 80deg); // #8080ff

事例代码

.p1 {
    // 让颜色变亮
    color:scale-color(#5c7a29, $lightness: +30%);
}

.p2 {
    // 让颜色变暗
    color:scale-color(#5c7a29, $lightness: -15%);
}

.p3 {
    // 降低颜色透明度
    color:scale-color(#5c7a29, $alpha: -40%);
}

编译为

.p1 {
    color: #95c249;
}

.p2 {
    color: #4e6823;
}

.p3 {
    color: rgba(92, 122, 41, 0.6);
}

调试相关

@debug

@debug 打印表达式的值,方便调试。

$font-sizes: 10px + 20px;
    $style: (
        color: #bdc3c7
    );
.container {
    @debug $style;
    @debug $font-sizes;
}

输出结果

Debug:(color: #bdc3c7)
Debug:30px

@error

@error 显示错误信息

@mixin reflexive-position($property, $value) {
  @if $property != left and $property != right {
    @error "Property #{$property} must be either left or right.";
  }

  $left-value: if($property == right, initial, $value);
  $right-value: if($property == right, $value, initial);

  left: $left-value;
  right: $right-value;
  [dir=rtl] & {
    left: $right-value;
    right: $left-value;
  }
}

.sidebar {
  @include reflexive-position(top, 12px);
  //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Error: Property top must be either left or right.
}

输出结果

Error: "Property top must be either left or right."
  ╷
3 │     @error "Property #{$property} must be either left or right.";
  │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ╵
  example.scss 3:5   reflexive-position()
  example.scss 19:3  root stylesheet

@warn

@warn显示警告性建议,会显示堆栈信息。

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

显示警告信息

Warning: Unknown prefix wekbit.
    example.scss 6:7   prefix()
    example.scss 16:3  root stylesheet

总结

内容知识比较多,通过查阅 Sass 官方文档和阅读文章翻译,收集整理常用 Sass 知识,方便在阅读 element-plus 组件库源码查阅

上一篇下一篇

猜你喜欢

热点阅读