archivo _handle.scss:
@import "_themes";
$theme-map: () !global;
@mixin themeify {
//遍历主题map
@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
@function themed($key) {
@return map-get($theme-map, $key);
}
//获取背景颜色
@mixin backgroundColor($color) {
@include themeify {
background-color: themed($color);
}
}
//获取字体颜色
@mixin fontColor($color) {
@include themeify {
color: themed($color);
}
}
//获取边框颜色
@mixin borderColor($color) {
@include themeify {
border-color: themed($color);
}
}
//获取边框底部颜色
@mixin borderBtmColor($color) {
@include themeify {
border-bottom-color: themed($color);
}
}
// 获取向下三角形
@mixin borderDownArrow($color){
@include themeify {
border-color: transparent transparent themed($color) themed($color);
}
}
//遮罩层
@mixin boxShadow($Num,$shadow,$inset:inset) {
@include themeify {
box-shadow:$Num themed($shadow) $inset;
-webkit-box-shadow:$Num themed($shadow) $inset;
}
}
//2个颜色叠加的遮罩层
@mixin boxShadow2($Num,$shadow,$Num2,$shadow2) {
@include themeify {
box-shadow: $Num themed($shadow),$Num2 themed($shadow2);
}
}
// 获取透明度
@mixin opacityNum($color) {
@include themeify {
opacity: themed($color);
}
}
// 渐变遮罩层
@mixin maskLinearGradient($deg,$color,$per,$from) {
@include themeify {
-webkit-mask: linear-gradient($deg,themed($color) $per,$from);
}
}
// 渐变背景图片
@mixin bImgLinearGradient($drc,$from,$to) {
@include themeify {
background-image: -webkit-linear-gradient($drc,themed($from),themed($to));
background-image: linear-gradient($drc,themed($from),themed($to));
}
}
//背景图片
@mixin imageThemeURL($path) {
@each $themename , $theme in $themes {
[data-theme = '#{$themename}'] & {
background-image: url($themename +'/'+ $path);
@content;
}
}
}
//重置样式
@mixin resetCss($themename){
@each $themename , $theme in $themes {
[data-theme = '#{$themename}'] & {
@content;
}
}
}
Archivo _themes.scss: las definiciones de color están aquí
$themes:(
theme_1:(
bodyBg:#0b1651,
fontColor: #0de1f6,
borderColor:#0de1f6
),
theme_2:(
bodyBg:#000,
fontColor: #2e85fe,
borderColor:#2e85fe
)
);
Ejemplo de uso:
Importe el archivo "_handle";
<style scoped lang="scss">
@import "assets/css/themes/_handle";
body{
@include backgroundColor('bodyBg');
@include fontColor('fontColor');
@include imageThemeURL('img/icon_chart.png');
@include boxShadow(0 0 10px 2px,'mtopTabConSd');
@include bImgLinearGradient(to bottom,'sytleSingleMoreOnBgfrom','sytleSingleMoreOnBgto');
@include boxShadow2(0px 0px 0px 2px,'sytleSingleMoreOnSd1',0px 0px 0px 3px,'borderColor')
}
</style>
Configuración de App.vue:
let theme=(type)=>{
const store = useStore();
store.commit('updateTheme', type);
document.documentElement.setAttribute( "data-theme", type);
};
let skinClass=getLocationStorage(GLOBAL_THEME);
if(skinClass=='undefined'||skinClass==undefined){
skinClass=store.state.themeType;
};
//默认颜色
theme(skinClass);
//切换颜色
let changeThemeCk=(skinClass)=>{
theme(skinClass);
}
Configuración de index.js en el archivo de la tienda:
state() {
return {
themeType:'theme_1'
};
},
mutations:{
/**更新主题 */
updateTheme(state,type){
let skinClass=getLocationStorage(GLOBAL_THEME);
if(skinClass=='undefined'||skinClass==undefined){
skinClass=state.themeType;
}else{
state.themeType=skinClass;
};
if(skinClass!==type){
let themeIndex=type&&type.split('_')[1]||1;
setLocationStorage(GLOBAL_THEME,type);
setLocationStorage(GLOBAL_THEME_INDEX,themeIndex);
window.location.reload() //手动刷新才能生效
};
}
}
archivo de almacenamiento.js:
/*获取*/
export function getLocationStorage(key){
return window.localStorage.getItem(key);
};
/**保存 */
export function setLocationStorage(key,value){
return window.localStorage.setItem(key,value);
}
/**删除 */
export function removeLocationStorage(key){
return window.localStorage.removeItem(key);
}
/**获取对象 */
export function getobjectLocalStorage(key){
return JSON.parse(window.localStorage.getItem(key));
}
/***保存对象 */
export function setobjectLocalStorage(key, value){
window.localStorage.setItem(key,JSON.stringify(value));
}
Puntos a tener en cuenta:
El uso de themeify para cambiar la máscara empaquetará todos los estilos de tema correspondientes y el tamaño del archivo será grande, lo que no es muy amigable (si hay muchas máscaras, no se recomienda su uso, el archivo de estilo será muy grande) .
![](https://img-blog.csdnimg.cn/img_convert/87bad4edc15f4f3892609e563be43629.png)
Uso recomendado:
Puede definir diferentes estilos de tema en el componente y luego importar el archivo de tema correspondiente.
![](https://img-blog.csdnimg.cn/img_convert/d93b3bec05914863a8cb6f550ac9ee61.png)
Archivo variable.scss: defina el color (hay un color global, puede definir una variable de color global por separado).
$bodyBg:rgba(26,57,150,.34);
archivo index.scss:
@import ‘全局颜色变量’;
@import 'variable';/*当前组件对应颜色变量*/
body{
background-color:$bodyBg;
}
Importe el archivo de tema correspondiente en el componente xx.vue:
/***导入对应主题样式 */
import(`./${store.state.themeType}/css/index.scss`);