使用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
)
)
在该文件我们定义两套主题,分别为default
和dark
二 定义主题匹配文件
在实际项目中,通过调用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
文件夹下应该是这几个文件
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>
示例:
看了不少教程,决定还是好好总结一番,写一篇拿来就能用的文章,让同样碰到该问题的小伙伴能够少走弯路.