⛳️前言

以往拟定款式一直是用的css或许less,这次触摸到的项目用的scss,然后就赶忙过来学一下!

css预处理器

css指层叠款式表 (Cascading Style Sheets),是一门非程序式言语,没有变量、函数、scope(作用域)等概念。

我认为css有三个最大的缺点

◾️ css并不存在逻辑。这点是我认为css最短缺的当地,不过目前貌似并没有任何一个工具能解决这个问题,css的动态调整仍然时js在做。

◾️ css自身无适宜的变量机制,尽管有–varible的语法,但是原生css的变量机制很难用。

◾️ css无法嵌套,导致css的可读性并不高,大部分时分便是只要写代码的人看看css,接手的人很简单一脸懵。

⁉️这样的缺陷可能会导致以下问题

◾️ 冗余度高:需求书写许多看似没有逻辑的代码

◾️ 不方便保护及扩展,难以复用

◾️ css没有很好的核算才干

一般来说,非前端工程师往往会由于短少css编写经验而很难写出安排良好且易于保护的CSS代码。

鉴于这些问题,css预处理器界说出了一种新的言语,其基本思想是,用一种专门的编程言语,进行 Web 页面款式规划,再经过编译器转化为正常的 CSS 文件,以供项目运用。它使得css愈加简洁、方便修改、可读性强、适应性强而且更易于代码的保护。

css预处理器包括less,scss,sass,stylus

sass是由buby言语编写的一款css预处理言语,和html相同有严格的缩进风格,和css编写标准有着很大的出入,是不运用花括号和分号的,所以不被广为承受。

SCSS 和 CSS 写法无差别,这也是 Sass 后来越来越受大众喜欢原因之一。简单点说,把你现有的“.css”文件直接修改成“.scss”即可运用。Sass 从第三代开端,放弃了缩进式风格,而且完全向下兼容普通的 CSS 代码,这一代的 Sass 被称为 Scss 。

// sass
#sidebar
   width: 30%
   background-color: #faa
// scss
#sidebar {
   width: 30%;
   background-color: #faa;
}

简单了解之后,让咱们进入正题!

预备工作

scss需求经过编译为css才干被浏览器识别,咱们直接运用webpack进行编译。

相关:概念 | webpack 中文文档

假如懒得自己动手装备,能够直接运用在线平台将scss编译成cssSassMeister | The Sass Playground!

示例文件结构:

这么好用的scss你干嘛不用!

首先装置css-loader、style-loader、node-sass、sass-loader。

npm install css-loader style-loader --save-dev
npm install node-sass sass-loader --save-dev

webpack.config.js装备文件中增加对应的loader,完好的装备图如下:

const path = require("path");
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
    entry: "./src/index",
    output: {
        filename: "[name].js",
        path: path.join(__dirname, "./dist"),
    },
    module: {
        rules: [
            {
                test: /.scss/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /.vue$/,
                use: 'vue-loader'
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin()
    ],
    mode: "production"
};

创建index.scss,然后在进口文件引进

// src/index.scss
$border-color: #aaa; //声明变量
.container {
    $border-width: 1px;
    border: $border-width solid $border-color; //运用变量
}
// src/index.js
import './index.scss'

后边咱们将在index.scss中编写scss代码,然后运转npx webpack,等候成果的输出!

☎️留意

◾️ 运用npx:npm install -g npx

能够参阅:npx运用方法

◾️ 运转后控制台可能会报错短少vue-loader,那就npm i vue-loader,我自己后边运转的时分还报以下的错,解决方法是npm i vue@3.2.26

这么好用的scss你干嘛不用!

让咱们开端吧!刻不容缓刻不容缓!!

scss

运用变量

SCSS中的变量以$最初。

$border-color: #aaa; //声明大局变量
.container {
    $border-width: 1px;//声明部分变量
    border: $border-width solid $border-color; //运用变量
}

在这个比方中,咱们界说了两个变量,其间$border-color在大括号之外称为大局变量,它任何当地都能够运用,$border-width是在.container之内声明的,是部分变量,只要.container内部才干运用。

编译后的css:

.container {
    border:1px solid #aaa; //运用变量
}

SCSS相当于模板引擎,编译的过程中用变量的值去替代变量所占据的方位。

☎️留意

◾️ SCSS中变量名运用中划线或下划线都是指向同一变量的。

◾️ 后界说的变量声明会被忽略,但赋值会被履行,这一点和ES5中var声明变量是相同的。

所以,假如在上面代码的基础上,再界说一个大局变量$border_color:#ccc,那他们将会指向同一个变量,.container的值会被第二次界说的变量覆盖。

好像看过不区分的原因,但是忘记了

嘿嘿找到了!这是Sass 早期的历史遗留问题,其时它只答应在标识符称号中运用下划线。一旦 Sass 增加了对连字符的支撑以匹配 CSS 的语法,这两者就等同于,使迁移更简单。

嵌套规矩

有些时分,咱们为了更详细的定位元素,所以在款式中给子元素款式时咱们可能会这么写

/*.father写了许多遍*/
.father ul {
    border: 1px solid #aaa;
    list-style: none;
}
.father ul:after {
    display: block;
    content: "";
    clear: both;
}
.father ul li {
    float: left;
}
.container ul li>a {
    display:inline-block;
    padding:6px 12px;
}

假如用scss的话,能够这么写

嵌套选择器

/*scss*/
.father ul {
    border:1px solid #aaa;
    list-style:none;
    li {
        float:left;
    }
    li>a {
        display:inline-block;
        padding:6px 12px;
    }
}
.father ul:after {
    display:block;
    content:"";
    clear:both;
}

嵌套中的父级选择器

scss中运用&表明选中当时元素的父元素,也便是父级选择器

.father ul {
    border:1px solid #aaa;
    list-style:none;
    li {
        float:left;
    }
    &:after {
        display:block;
        content:"";
        clear:both;
    }
}

☎️留意

◾️ 只能在嵌套内部运用父级选择器,否则SCSS找不到父级元素会直接报错。

◾️ 伪类选择器中,父级选择器十分常用

嵌套组合选择器

在嵌套规矩中能够写任何css代码,包括群组选择器(,),子代选择器(>),同层相邻组合选择器(+)、同层整体组合选择器(~)等等

/*scss*/
.father ul {
    border:1px solid #aaa;
    list-style:none;
    li {
        float:left;
        >a {
            display:inline-block;
            padding:6px 12px;
        }
    }
    &:after {
        display:block;
        content:"";
        clear:both;
    }
}

子代选择器能够写在外层选择器右边(如下述比方)也能够写在内层选择器左面(如上述比方)。

li >{
    a {
        display:inline-block;
        padding:6px 12px;
    }
}

☎️留意

◾️ 写在外层选择器右边时要特别留意,它会作用于全部嵌套的选择器上,所以尽量不要选用这类写法,扩展性不强,也简单犯错

嵌套特点

scss识别一个特点以分号结束时则判断为一个特点,以大括号结束时则判断为一个嵌套特点,规矩是将外部的特点以及内部的特点经过中划线连接起来构成一个新的特点。

比方:

li {
    border:1px solid #aaa;
    border-left:0;
    border-right:0;
}

用scss

li {
    border:1px solid #aaa {
        left:0;
        right:0;
    }
}

导入scss文件

开发一个大型项目的时分,css文件不止一个,css供给了@import指令在css内部引进另一个css文件,浏览器只要在履行到@import句子后才会去加载对应的css文件,导致页面性能变差,所以基本不运用。

SCSS中的@import指令跟原生的不太相同。

导入变量的优先级问题-变量默许值(!default)

/*App1.scss*/
$border-color:#aaa; //声明变量
@import App2.scss;  //引进另一个SCSS文件
.container {
    border:1px solid $border-color; //运用变量
}
/*App2.scss*/
$border-color:#ccc; //声明变量
/*生成的css文件*/
.container {
    border:1px solid #ccc; //运用变量
}

咱们能够看到,变量$border-color的值被引进的scss文件中的同名变量所污染覆盖,假如咱们不想这种工作发生,咱们能够运用变量默许值。

/*App1.scss*/
$border-color:#aaa; //声明变量
@import App2.scss;  //引进另一个SCSS文件
.container {
    border:1px solid $border-color; //运用变量
}
/*App2.scss*/
$border-color:#ccc !default; //声明变量
/*生成的css文件*/
.container {
    border:1px solid #aaa; //运用变量
}

运用!default后,导入的文件App2.scss只在文件中不存在border−color时起作用,若App1.scss中已经存在了border-color时起作用,若App1.scss中已经存在了border-color变量,则App2.scss中的$border-color不收效。

☎️留意

◾️ !default只能运用于变量中。

嵌套导入-部分导入

上面的比方是大局导入App2.scss,其实咱们也能够部分导入

/*App1.scss*/
$border-color:#aaa; //声明变量
.container {
    @import App2.scss;  //引进另一个SCSS文件
    border:1px solid $border-color; //运用变量
}
/*App2.scss*/
$border-color:#ccc !default; //声明变量
p {
    margin:0;
}
/*生成的css文件*/
.container {
    border:1px solid #aaa; //运用变量
}
.container p {
    margin:0;
}

成果便是将App2.scss中的全部内容直接写入到App1.scss的.container选择器中

运用原生@import

某些情况下咱们不得不运用原生@import时了,SCSS也为咱们处理了这种情况,直接导入css文件即可

@import 'App.css';

注释

SCSS中的注释有两种

◾️ /注释/:这种注释会被保留到编译后的css文件中。

◾️ //注释:这种注释不会被保留到编译后生成的css文件中。

混合器@mixin(宏界说)

声明一个函数

运用@mixin指令声明一个函数,提高复用率

@mixin border-radius{
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    color:red;
}

混合器作用域内的特点都是return的值,除此之外,还能够为函数传参数。

@mixin get-border-radius($border-radius,$color){
    -moz-border-radius: $border-radius;
    -webkit-border-radius: $border-radius;
    border-radius: $border-radius;
    color:$color;
}

也能够设置混合器的默许值。

真不错

@mixin get-border-radius($border-radius:5px,$color:red){
    -moz-border-radius: $border-radius;
    -webkit-border-radius: $border-radius;
    border-radius: $border-radius;
    color:$color;
}

运用函数

运用函数的关键字为@include,多个参数时,传参指定参数的名字,能够不必考虑传入的次序。

.container {
    border:1px solid #aaa;
    @include get-border-radius;         //不传参则为默许值5px
    @include get-border-radius(10px,blue);   //传参
}
/*多个参数时,传参指定参数的名字,能够不必考虑传入的次序*/
.container {
    border:1px solid #aaa;
    @include get-border-radius;         //不传参则为默许值5px
    @include get-border-radius($color:blue,$border-radius:10px);   //传参
}

☎️留意

◾️ 混合器中能够写全部scss代码。

@function

没错我便是看了这个,所以才过来看scss

函数是运用@function规矩界说的,该规矩编写为@function <name> (<arguments...>){...}。函数的称号能够是任何 Sass 标识符。它只能包括通用句子,以及@return规矩,该规矩指示要用作函数调用成果的值。运用惯例 CSS 函数语法调用函数。

/*scss语法*/
@function pow($base, $exponent) {
  $result: 1;
  @for $_ from 1 through $exponent {
    $result: $result * $base;
  }
  @return $result;
}
.sidebar {
  float: left;
  margin-left: pow(4, 3) * 1px;
}
/*css语法*/
.sidebar {
  float: left;
  margin-left: 64px;
}

☎️留意

◾️ 尽管从技术上讲,函数可能会发生诸如设置大局变量之类的副作用,但强烈建议不要这样做。

◾️ 运用mixins 来发生副作用,并运用函数来核算值。

参数

参数,答应在每次调用函数时。自界说函数的行为。参数在@function函数称号之后的规矩中,指定为用括号括起来的变量称号列表。该函数有必要以 SassScript表达式的方式。运用相同数量的参数调用。这些表达式的值,在函数体中作为相应的变量可用。

参数列表也能够有尾随逗号!这使得重构款式表时更简单防止语法错误。

可选参数

能够经过界说一个默许值来使参数成为可选参数,假如该参数未传递,则将运用该默许值。默许值运用与变量声明相同的语法

/*scss*/
@function invert($color, $amount: 100%) {
  $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;
}

关键字参数

能够按称号传递参数。这对于具有多个可选参数的函数或带有布尔参数的函数特别有用,这些参数的含义在没有称号的情况下并不显着。关键字参数运用与变量声明和可选参数相同的语法。

@function scale-color($primary-color, $lightness){...}
$primary-color: #036;
.banner {
  background-color: $primary-color;
  color: scale-color($primary-color, $lightness: +40%);
}
.banner {
  background-color: #036;
  color: #0a85ff;
}

接纳恣意参数

假如@function声明中的最后一个参数以结束 ... ,则该函数的全部额定参数都作为列表传递给该参数。此参数称为参数列表。

/*scss*/
@function sum($numbers...) {
  $sum: 0;
  @each $number in $numbers {
    $sum: $sum + $number;
  }
  @return $sum;
}
.micro {
  width: sum(50px, 30px, 100px);
}
/*css*/
.micro {
  width: 180px;
}

接纳恣意关键字参数

meta.keywords()函数承受一个参数列表并回来任何额定的关键字,这些关键字作为从参数称号(不包括$)到这些参数值的映射传递给函数。假如咱们从未将参数列表传递给meta.keywords()函数,则该参数列表将不答应额定的关键字参数,这个能够防止意外拼错任何参数称号。

传递恣意参数

就像参数列表答应函数承受恣意方位或关键字参数相同,咱们能够运用相同的语法将方位参数和关键字参数传递给函数。

/*scss*/
$widths: 50px, 30px, 100px;
.micro {
  width: min($widths...);
}
/*css*/
.micro {
  width: 30px;
}

而且由于参数列表同时跟踪方位参数和关键字参数,所以咱们能够运用它同时将两者传递给另一个函数。这使得为函数界说别名变得十分简单!

@function fg($args...) {
  @warn "The fg() function is deprecated. Call foreground() instead.";
  @return foreground($args...);
}

@return

@return规矩指示用作调用函数成果的值。

它只答应在@function正文中,而且每个@function有必要以@return结束。当遇到@return时立即结束函数并回来其成果。

@use "sass:string";
@function str-insert($string, $insert, $index) {
  // Avoid making new strings if we don't need to.
  @if string.length($string) == 0 {
    @return $insert;
  }
  $before: string.slice($string, 0, $index);
  $after: string.slice($string, $index);
 @return $before + $insert + $after;
}

承继@extend

搞什么?下降代码量是吧,我直接面向对象!

界说被承继的款式

运用%界说一个被承继的款式,类似静态言语中的抽象类,自身不起作用,只用于被其他人承继。

%border-style {
  border:1px solid #aaa;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

承继款式

经过关键字@extend即可完结承继。

.container {
        @extend %border-style;
}

什么?上述比方中看不出混合器与承继之间的差异,那你可看这个!

.container {
        @extend %border-style;
        color:red;
}
.container1 {   //承继另一个选择器
        @extend .container;
}

操作符

SCSS供给了标准的算术运算符,例如+、-、*、/、%

/*SCSS*/
width: 600px / 960px * 100%;
/*编译后的CSS*/
width: 62.5%;

跳出根元素@at-root

@at-root 从字面上解说便是跳出根元素。当你选择器嵌套多层之后,想让某个选择器跳出,此刻就能够运用 @at-root

/*scss*/
.wrapper {
    width:100%;
    height:100%;
    @at-root .active{
        color:red
    }
}
/*css*/
.wrapper {
    width:100%;
    height:100%;
}
.active{
    color:red
}

@content

@content 用在 mixin 里边的,当界说一个 mixin 后,而且设置了 @content@include 的时分能够传入相应的内容到 mixin 里边

这么好用的scss你干嘛不用!

map-get

map-get(map,key) 函数的作用是依据 key 参数,回来 key 在 map 中对应的 value 值。假如 key 不存在 map 中,将回来 null 值。此函数包括两个参数:

map:界说好的 map。 key:需求遍历的 key。

假定要获取 facebook 键值对应的值 #3b5998,咱们就能够运用 map-get() 函数来完成:

这么好用的scss你干嘛不用!

map-merge

兼并两个 map 构成一个新的 map 类型,即将 map2 增加到 map1的尾部

$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

循环

@for

@for 指令包括两种格式:@for $var from <start> through <end>或许 @for $var from <start> to <end>,差异在于 through 与 to 的含义:当运用 through 时,条件范围包括startend的值,而运用 to 时条件范围只包括start的值不包括end的值。别的,$var 能够是任何变量,比方 $i;<start><end>有必要是整数值。

不必@for时分

.wes {
    /* 多出部分用省略号表明 , 用于一行 */
    overflow:hidden;
    word-wrap:normal;
    white-space:nowrap;
    text-overflow:ellipsis;
}
.wes-2 { 
    /* 适用于webkit内核和移动端 */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
} 
.wes-3 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}
.wes-4 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
}

用上@for

太牛了!

@for $i from 1 through 4 {
  .wes-#{$i} {
    overflow: hidden;
    @if ($i==1) {
      word-wrap: normal;
      white-space: nowrap;
      text-overflow: ellipsis;
    } @else {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: $i;
    }
  }
}

@each 循环

这么好用的scss你干嘛不用!

对象操作(key:value)

原始版

h1 {
  font-size: 2em; }
h2 {
  font-size: 1.5em; }
h3 {
  font-size: 1.2em; }

用上对象操作

@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
  #{$header} {
    font-size: $size;
  }
}

less和scss的差异

了解了一圈scss后,咱们也被忘记了less,让咱们看看他俩的差异,gogogo!

相同点

less和scss都是css的预处理器,能够拥有变量,运算,承继,嵌套的功用,运用两者能够使代码愈加的便于阅览和保护。

都能够经过自带的插件,转成相对应的css文件。

都能够参数混入,能够传递参数的class,就像函数相同

嵌套的规矩相同,都是class嵌套class

不同点

声明和运用变量:less用@符号,scss用$符号表明

变量插值:less选用@{XXXX}的方式,scss选用${XXXX}的方式

能够用为less和scss声明变量,变量作为css的选择器

@main-top : search;
.@{ main-top } {
    font-size24pxcolor : #fff;
}
// 是用LESS,界说类,类选择器选中search标签,给其设置css款式
 $main-top : search;
.${ main-top } {
        font-size24pxcolor : #fff;
}
// 是用SCSS,界说类,类选择器选中search标签,给其设置css款式

scss支撑条件句子(if、else、for循环等),less不支撑


/* Sample Sass “if” statement */
 
@if lightness($color) > 30% {
 
} @else {
 
}
 
/* Sample Sass “for” loop */
 
@for $i from 1 to 10 {
  .border-#{$i} {
   border: #{$i}px solid blue;
  }

运用外部css文件方法不同

SCSS运用的css文件名有必要以‘_’最初(下划线),文件名假如以下划线最初的话,sass会认为该文件是一个运用文件,不会将它转成css文件

// 源代码:
@import "_main.css";
@import "_layout.css";
@import "_text.css";

颜色函数

调整色相的话,LESS运用spin()的函数;SCSS运用名为adjust_hue()的函数

/*less*/
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
 /*scss*/
 $state-success-border: darken(adjust_hue($state-success-bg, -10), 5%);

引证父选择器&符号的运用

LESS和SCSS都能够运用&符号表明父选择器,但是SCSS的&符号只能出现在一个组合选择器的开端方位,LESS则没有这个约束

/*less*/
.bg-variant(@color) {
  background-color: @color;
  a&:hover,
  a&:focus {
   background-color: darken(@color, 10%);
  }
}
 /*scss*/
a {
  font-weight: bold;
  text-decoration: none;
 &:hover { text-decoration: underline; }
  body.firefox & { font-weight: normal; }
}

怎么运用scss一键换肤?

许多时分咱们需求一键换肤的功用,刚触摸前端时分咱们是直接别的建立一个css文件,经过更换css文件来达到这个作用。但是这样其实会形成许多的代码冗余,假如用scss的写法,运用scss的长处提早界说一张套css环境变量系统会大大优化代码!

以下将会用一个demo来完成一键换肤的作用,那咱们开端吧

项目的目录结构

src
├── App.vue
├── main.js
├── router
│   └── index.js
├── store
│   └── index.js
├── style
│   ├── settings
│   │   └── variable.scss  // 款式变量界说文件
│   └── theme
│       ├── default
│       ├── index.scss // 主题进口文件
│       └── old
└── views
    ├── Home.vue // 主题切换页面
    ├── List.vue
    └── Mine.vue

环境预备

npm i sass

npm i -D sass-loader @10.1.0

留意 sass-loader 装置需求指定版本 假如装置最新版本会报错 this.getOptions 这个方法未界说

npm i -S normalize.css

运用 normalize.css 初始化页面款式*

界说变量

提早把一些常用的主题色,字体大小,以及边距这种与视觉沟通好,然后界说对应的变量。

这么好用的scss你干嘛不用!

界说主题

默许主题:./src/theme/default/index.scss

/* 默许主题色 */
@import "../../settings/variable.scss";
$theme-default: (
  color: $info,
  font-weight: $font-weight-bold,
  font-size: $font-size-lg,
);

老年主题:./src/theme/old/index.scss

/* 老年主题色 */
@import "../../settings/variable.scss";
$theme-old: (
  color: $danger,
  font-weight: $font-weight-bold,
  font-size: $font-size-slg,
);

进口文件:./src/theme/index.scss

界说混合指令,切换主题,并将主题中的全部规矩增加到 theme-map 中

@import "../settings/variable.scss";
@import "./default/index.scss";
@import "./old/index.scss";
$themes: (
  default: $theme-default,
  old: $theme-old,
  /*...其他主题*/
);
$theme-map: null;
// 第三步: 界说混合指令, 切换主题,并将主题中的全部规矩增加到theme-map中
@mixin themify() {
  @each $theme-name, $map in $themes {
    // & 表明父级元素  !global 表明覆盖原来的
    [data-theme="#{$theme-name}"] & {
      $theme-map: () !global;
      // 循环兼并键值对
      @each $key, $value in $map {
        $theme-map: map-merge(
          $theme-map,
          (
            $key: $value,
          )
        ) !global;
      }
      // 表明包括 下面函数 themed()
      @content;
    }
  }
}
@function themed($key) {
  @return map-get($theme-map, $key);
}

vue.config.js 装备项处理

在装备项中运用 CSS 插件主动注入大局变量款式

运用 webpack 自界说插件遍历主题目录文件,主动生成自界说主题目录数组

const fs = require("fs");
const webpack = require("webpack");
// 获取主题文件名
const themeFiles = fs.readdirSync("./src/style/theme");
let ThemesArr = [];
themeFiles.forEach(function (item, index) {
  let stat = fs.lstatSync("./src/style/theme/" + item);
  if (stat.isDirectory() === true) {
    ThemesArr.push(item);
  }
});
//运用 CSS 插件主动注入大局变量款式
module.exports = {
  css: {
    loaderOptions: {
      scss: {
        // 留意: 在sass-loader v8 中,这个选项是prependData
        additionalData: `@import "./src/style/theme/index.scss";`,
      },
    },
  },
  configureWebpack: (config) => {
    return {
      plugins: [
        new webpack.DefinePlugin({
          THEMEARR: JSON.stringify(ThemesArr),
          THEMEFILES: JSON.stringify(themeFiles),
        }),
      ],
    };
  },
};

主题色切换

在 App.vue 文件下的 mounted 中将 body 增加一个自界说的 data-theme 特点,并将其设置为 default

这么好用的scss你干嘛不用!

切换 js 逻辑完成

初始化页面时,获取到默许主题

// Home.vue
mounted() {
  this.themeValue = THEMEARR;
  this.currentThemeIndex = this.themeValue.findIndex(
    (theme) => theme === "default"
  );
  this.currentTheme = this.themeValue[this.currentThemeIndex];
},

把选择的主题赋值给自界说特点 data-theme

// Home.vue
// 核心切换逻辑
methods: {
  onConfirm(currentTheme) {
    this.currentTheme = currentTheme;
    this.showPicker = false;
    this.currentThemeIndex = this.themeValue.findIndex(
      (theme) => theme === currentTheme
    );
    document
      .getElementsByTagName("body")[0]
      .setAttribute("data-theme", THEMEARR[this.currentThemeIndex]);
  },
}

归纳运用

//Home.vue
<script>
export default {
  name: "Home",
  components: {},
  data() {
    return {
      currentTheme: "default",
      currentThemeIndex: 0,
      // themeCName: ["默许", "白叟"],
      themeValue: [],
      gridIcon: ["location-o", "like-o"],
      gridNum: [8, 4],
      columnNum: [4, 2],
      showPicker: false,
    };
  },
  methods: {
    onConfirm(currentTheme) {
      this.currentTheme = currentTheme;
      this.showPicker = false;
      this.currentThemeIndex = this.themeValue.findIndex(
        (theme) => theme === currentTheme
      );
      document
        .getElementsByTagName("body")[0]
        .setAttribute("data-theme", THEMEARR[this.currentThemeIndex]);
    },
  },
  mounted() {
    this.themeValue = THEMEARR;
    this.currentThemeIndex = this.themeValue.findIndex(
      (theme) => theme === "default"
    );
    this.currentTheme = this.themeValue[this.currentThemeIndex];
  },
};
</script>
<style lang="scss">
.home {
  padding: 10px;
  .t-home-title,
  .t-home-sub-title,
  .t-home-info {
    @include themify() {
      color: themed("color");
      font-weight: themed("font-weight");
      font-size: themed("font-size");
    }
  }
}
</style>
<script>
export default {
  name: "Home",
  components: {},
  data() {
    return {
      currentTheme: "default",
      currentThemeIndex: 0,
      // themeCName: ["默许", "白叟"],
      themeValue: [],
      gridIcon: ["location-o", "like-o"],
      gridNum: [8, 4],
      columnNum: [4, 2],
      showPicker: false,
    };
  },
  methods: {
    onConfirm(currentTheme) {
      this.currentTheme = currentTheme;
      this.showPicker = false;
      this.currentThemeIndex = this.themeValue.findIndex(
        (theme) => theme === currentTheme
      );
      document
        .getElementsByTagName("body")[0]
        .setAttribute("data-theme", THEMEARR[this.currentThemeIndex]);
    },
  },
  mounted() {
    this.themeValue = THEMEARR;
    this.currentThemeIndex = this.themeValue.findIndex(
      (theme) => theme === "default"
    );
    this.currentTheme = this.themeValue[this.currentThemeIndex];
  },
};
</script>
<style lang="scss">
.home {
  padding: 10px;
  .t-home-title,
  .t-home-sub-title,
  .t-home-info {
    @include themify() {
      color: themed("color");
      font-weight: themed("font-weight");
      font-size: themed("font-size");
    }
  }
}
</style>

作用图

这么好用的scss你干嘛不用!

到这儿scss就入门结束啦!!接下来就看大家了嘻嘻嘻!

引荐阅览

怎么运用 SCSS 完成一键换肤

传闻你还不会SCSS?带你把握scss全部知识点(上):Sass的介绍、装置和文件编译