Skip to content

前端主题切换解决方案

使用sass切换主题

image-20220930214456344

使用sass切换主题,也就是一键换肤的功能,记录一下功能代码

就是给html根标签设置一个data-theme属性,然后通过js切换data-theme的属性值,scss根据此属性来判断使用对应主题变量。这里可以选择持久化vux或接口来保存用户选择的主题。

安装sass

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

配置sass(如果需要)

vite.config.ts

typescript
export default defineConfig({
  css: {
    //css预处理
    preprocessorOptions: {
      scss: {
        ///引入var.scss全局预定义变量
        additionalData: '@import "./src/assets/styles/global.scss";',
      },
    },
  },
});

切换主题至少需要用到两个文件

assets/styles/_handle.scssassets/styles/_themes.scss

_themes.scss

_themes.scss 中定义你的主题样式,可以多个

scss
$themes: (
    //主题1 默认
    Azur:
        (
            //文字主色和副色
            font-main-color: #555,
            font-secondary-color: #a0a0a0,
            font-hover-color: rgb(126, 204, 230),

            //导航主色和hover
            menu-font-color: #a0a0a0,
            menu-font-hover-color: #555,

            //导航背景
            menu-background: rgba(255, 255, 255, 0.8),
            //主色
            bg-main-color: rgb(176, 223, 238),
            bg-secondary-color: rgba(176, 223, 238,.5),

            //主内容背景色
            main-bg-color: #fff,
            main-border-color: rgb(228, 228, 228),

            //滚动条
            scrollbar-bg-color: rgba(176, 223, 238, 0),
            scrollbar-border-color: rgba(176, 222, 238, 1),
            scrollbar-hover-color: rgb(126, 204, 230),
        ),
    //主题2 黑
    Dark:
        (
             //文字
             font-main-color: rgb(224, 224, 224),//主色
             font-secondary-color: #a0a0a0,//副色
             font-hover-color: rgb(255, 255, 255),//hover
 
             //导航
             menu-font-color: #a0a0a0,//主色
             menu-font-hover-color: #555,//hover
             menu-background: rgba(0, 0, 0, 0.8),//背景


             //背景色
             bg-main-color: rgba(0, 0, 0, 0.253),//主色
             bg-secondary-color: rgba(176, 223, 238,.5),//副色

            //BODY背景色滤镜
            body-color: rgba(0, 0, 0, 0.4),

 
             //主内容
             main-bg-color: rgba(0, 0, 0,.8),//背景色
             main-border-color: rgba(228, 228, 228,.4),//边框色

            //滚动条
            scrollbar-bg-color: rgba(0, 0, 0, 0.322),
            scrollbar-border-color: rgba(0, 0, 0, 0.8),
            scrollbar-hover-color: rgb(0, 0, 0, 0.5)
        )
);

_handle.scss

_handle.scss使用sass的map遍历、函数、map存取、混合器等相关知识

详细参考官方API文档

scss
//引入你的主题
@import "@/assets/styles/_themes.scss";

//此处用了sass的map遍历、函数、map存取、混合器等相关知识,
//遍历主题map
@mixin themeify {
  @each $theme-name, $theme-map in $themes {
    //!global 把局部变量强升为全局变量
    $theme-map: $theme-map !global;
    //这步是判断html的data-theme的属性值  #{}是sass的插值表达式
    //& sass嵌套里的父容器标识   @content是混合器插槽,像vue的slot
    [data-theme="#{$theme-name}"] & {
      @content;
    }
  }
}
//声明一个根据Key获取颜色的function 从主题色map中取出对应颜色
@function themed($key) {
  @return map-get($theme-map, $key);
}

//常用的开发场景下面三种背景颜色、字体颜色、边框颜色  还有其他可以自定义添加,比如阴影..
//获取背景颜色
@mixin background_color($color) {
  @include themeify {
    background-color: themed($color);
  }
}
//获取字体颜色
@mixin font_color($color) {
  @include themeify {
    color: themed($color);
  }
}
//获取边框颜色
@mixin border_color($color) {
  @include themeify {
    border-color: themed($color);
  }
}

项目中使用

html
<style lang="scss" scoped>
// 导入handle文件
@import "@/assets/styles/handle";

//使用@include即可
nav {
  @include background_color("menu-background");
  @include font_color("menu-font-color");
  box-shadow: 0 5px 6px -5px rgb(133 133 133 / 60%);

</style>

使用css变量切换