这几天在封装组件库,今天和大家一起使用scss,学习一些scss的基础语法。
先来看一下scss的优势
SCSS (Sass) 有以下几个主要优势:
- 可维护性:SCSS 允许使用变量、嵌套、混合、继承等特性,从而使样式表变得更加清晰、可读性增强。
- 更高效:SCSS 允许使用函数、循环等高级特性,使得样式定义更加高效。
- 更易扩展:SCSS 提供了组件化和模块化的技巧,可以更方便地扩展和维护代码。
- 更简单:SCSS 的语法比 CSS 更简洁易懂,允许编写更加简洁的样式表。
- 兼容性:SCSS 可以完全兼容 CSS,可以无缝地使用
再来看一下scss和其他对比
Scss/Less | Atomic CSS | css-in-js | |
---|---|---|---|
完全支持样式覆盖 | 是 | 是 | 需要使用className支持 |
支持rem布局 | 是 | 是 | 大部分库支持 |
可读性 | 强 | 稍弱 | 强 |
上手成本 | 较低 | 中 | 高 |
是否支持SSR | 天然支持 | 天然支持 | 需要额外支持 |
是否支持流式渲染 | 天然支持 | 天然支持 | 需要额外支持 |
支持postcss | 是 | 是 | 有自己的插件生态 |
看到scss这么多优势,接下来就让我们开启一段scss学习之旅吧!!!!
对原生css的支持
首先scss完全兼容css,可以使用css3在内的所有css语法进行书写
变量
scss中可以定义变量。常使用 $变量名:值
的形式来定义变量。并且支持变量的运算。
看下下面的例子
<style scoped lang="scss">
$Len:100px;
.class_A {
width: $Len;
height: 0.6 * $Len;
}
</style>
效果如下:
更优雅的scss写法
scss中的层级更清晰,更优雅,代码的可读性更高
看下面这个例子
.contain ul {
border:1px solid black;
list-style:none;
}
.contain ul:after {
display:block;
clear:both;
}
.contain ul li {
float:left;
}
.contain ul li > a {
display:inline-block;
padding:6px 12px;
}
上面的css是一个列表横向排布的例子,但是如果用scss重构
就会是下面的样子
/*scss*/
.contain ul {
border:1px solid black;
list-style:none;
li {
float:left;
}
li>a {
display:inline-block;
padding:6px 12px;
}
}
.contain ul:after {
display:block;
content:"";
clear:both;
}
&的作用
在scss中,我们可以使用&来选择当前元素的父元素
请看下面的代码
<template>
<div class="class_A">
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
$Len:100px;
.class_A {
width: $Len;
height: 0.6 * $Len;
background-color: #646cff;
&:hover {
background-color: darkorange;
}
}
</style>
我们定义了一个div,然后类名是class_A,我们为class_A添加鼠标移动过后颜色改变的特效时,可以通过&
来直接选中他。
鼠标移动前后如下
结合这些,我们可以对原生css的组合选择器进行简化书写,具体大家可以思考一下。
比如这样
div >{
a {
color: red;
}
}
函数式编写scss
scss提供了函数式编写的方案,想象一下下面的场景,我们需要定义三个方块,分别是红色,蓝色,和黄色,大小并不相同,同时每个方块鼠标移过后都会有一个暗淡的效果,我们应该如何去书写呢?
先来看一下原生的css
<template>
<div class="class_A">
</div>
<div class="class_B">
</div>
<div class="class_C">
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.class_A {
margin: 10px;
width: 100px;
height: 60px;
background-color: red;
}
.class_A:hover {
opacity: 0.6;
transition: all 0.6s;
}
.class_B {
margin: 10px;
width: 80px;
height: 48px;
background-color: blue;
}
.class_B:hover {
opacity: 0.6;
transition: all 0.6s;
}
.class_C {
margin: 10px;
width: 60px;
height: 36px;
background-color: yellow;
}
.class_C:hover {
opacity: 0.6;
transition: all 0.6s;
}
</style>
三种方块不同大小,颜色,同时鼠标移动会有一个特效
接下来让我们用scss做一个重构
在此之前让我们来先介绍一下scss函数的用法
我们通过@mixin
声明一个函数,然后通过@include
来使用
@mixin fun($w) {
// 定义了一个函数fun,接受一个参数
}
好了,我们正式开始重构我们的代码
<template>
<div class="class_A">
</div>
<div class="class_B">
</div>
<div class="class_C">
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
@mixin fun($w,$h,$bg) {
margin: 10px;
width: $w;
height: $h;
background-color: $bg;
&:hover {
opacity: 0.6;
transition: all 0.6s;
}
}
.class_A {
@include fun(100px,60px,red);
}
.class_B {
@include fun(80px,48px,blue);
}
.class_C {
@include fun(60px,36px,yellow);
}
</style>
同样的效果,更少的代码,更优雅的写法,更简洁的代码风格,更高的可读性和可维护性。
而在很多耦合度更高的情况下,这种写法能更大的提升代码的可维护性和可读性。
@each , @if , @else if , @else的学习
在@each变量的定义,其中包含的每个项目的列表中的值。
而其他的三个很明显是流程判断的指令,话不多说,我们继续使用上面的代码重构我们的需求。
先分析下我们的class,有A,B,C三种不同的状态。所以我们开始操作,请相信我这是最后一遍重构了。
<template>
<div class="class_A">
</div>
<div class="class_B">
</div>
<div class="class_C">
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss">
@mixin fun($w,$h,$bg) {
margin: 10px;
width: $w;
height: $h;
background-color: $bg;
&:hover {
opacity: 0.6;
transition: all 0.6s;
}
}
@each $state in A , B , C {
.class_#{$state} {
@if(#{$state} == A) {
@include fun(100px,60px,red);
}
@else if(#{$state} == B) {
@include fun(80px,48px,blue);
}
@else {
@include fun(60px,36px,yellow);
}
}
}
</style>
好耶,还是一样的。不过代码高级,优雅了太多啦。
面向对象
最后再说说scss中的继承的问题,我们可以向面向对象一样去继承。
我们通过@extend
来继承一个类,这个类可以是css中的class,也可以是我们定义的基类。
基类的定义:
%base-class {
//...
}
然后我们可以定义一个类来继承这个基类
.class_1 {
@extend %base-class;
// 也可以再写点,或者改基类的一些属性
}
我们甚至可以再定义一个类去继承class_1,这也是完全可以的。
.class_1--child {
@extend .class_1;
// 继续写点也行,改点基类属性也行
}
最后
入门scss之后,我们以后就正式开始组件的封装了。