tangyuxian
文章77
标签36
分类5
UI库-使用scss处理多主题切换功能

UI库-使用scss处理多主题切换功能

使用scss处理多主题的问题总结,拿来即用,少走弯路

项目当中有类似白天黑夜或者其它主题的切换需求,这类工作最好在项目构建之初便考虑到并且提前配置好,这里结合我在网上查到的一些方法还有实际工作需求,做一个总结.

一 定义主题文件

既然是多主题,就需要我们一开始就需要考虑到提前将UI中的色系及字体等情况做一个统一的配置,如下图,创建一个_themes.scss文件在静态资源目录下,我们一般放在工程中的/src/assets/css下.

$themes: (
  default:(
    /*字体*/
    font-size-lg : 18px,
    /*颜色*/
    bg-color: #fff,
    font-color:#000
  ),
  dark:(
    /*字体*/
    font-size-lg : 36px,
    /*颜色*/
    bg-color: #000,
    font-color:#fff
  )
)

在该文件我们定义两套主题,分别为defaultdark

二 定义主题匹配文件

在实际项目中,通过调用scss函数来匹配不同的主题,创建一个_themeify.scss文件

@import "./_themes.scss";

@mixin themeify {
  @each $theme-name, $theme-map in $themes {
    $theme-map: $theme-map !global;
    [data-theme=#{$theme-name}] & {
      @content;
    }
  }
}

@function themed($key) {
  @return map-get($theme-map, $key);
}

具体scss函数方法使用规则可以参照sass官网,这里用到了预处理中的控制指令,遍历每一项,!global关键词提权到全局.

三 如何使用

1 定义一个其它的scss文件,我们暂且取名为other.scss,使用方法如下:

@mixin home(){
    width: 100px;
    height: 100px;
    @include themeify{
        background-color: themed('bg-color');
        font-size: themed('font-size-lg')
    }
}

这里我们注意到,想要调用配置的主题颜色需要通过@include调用,并通过themed()函数将配置的变量名传入即可.

2 统一导出

创建一个index.scss用于统一的样式导出

@import "./_themeify.scss";
@import "./other.scss";

这样做的目的便于统一管理,结构清晰,此时css文件夹下应该是这几个文件

image-20220412223652204

3 配置全局引入

这里用vite举例,通过下述方式即可

export default defineConfig({
    css:{
        preprocessorOptions:{
          scss:{
            additionalData:'@import "@/assets/css/index.scss";'
          }
        }
  }
})

4 修改当前主题

在vue3工程中,可在根目录下修改index.html给body标签增加data-theme="default"属性

5 使用

vue项目中,可以像下面例子直接使用,无论是正常调用定义的预处理函数,还是直接调用主题颜色都可.

<template>
  <div class="wrapper">
    <div class="box">
      测试文字
    </div>
    <div>
      <button @click="changeTheme">切换主题</button>
    </div>
  </div>
</template>

<script setup lang="ts">
   import {ref} from "vue";
   //定义主题状态
   let themeType = ref<string>('default');
   /**
    * 改变主题
    */
   const changeTheme = ():void =>{
     themeType.value = themeType.value == 'default'?'dark':'default'
      document.getElementsByTagName('body')[0].setAttribute('data-theme',themeType.value)
   }
</script>
<style scoped lang="scss">
 .box{
   @include home();
   @include themeify{
    color: themed('font-color');
   }
 }
</style>

示例:

image-20220412223312012

image-20220412223407052

image-20220412223423699

image-20220412223449701

看了不少教程,决定还是好好总结一番,写一篇拿来就能用的文章,让同样碰到该问题的小伙伴能够少走弯路.

本文作者:tangyuxian
本文链接:https://www.tangyuxian.com/2022/04/12/%E5%89%8D%E7%AB%AF/UI%E5%BA%93/UI%E5%BA%93-%E4%BD%BF%E7%94%A8scss%E5%A4%84%E7%90%86%E5%A4%9A%E4%B8%BB%E9%A2%98%E5%88%87%E6%8D%A2%E5%8A%9F%E8%83%BD/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可