Vue implements skinning and avoids pits

  1. _handle.scss file:

@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;
    }
  }
} 
  1. _themes.scss file: color definitions are here

$themes:(
  theme_1:(
    bodyBg:#0b1651,
    fontColor: #0de1f6,
    borderColor:#0de1f6
  ),
  theme_2:(
    bodyBg:#000,
    fontColor: #2e85fe,
    borderColor:#2e85fe 
  )
);
  1. Example usage:

Import the "_handle" file;

<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>
  1. App.vue settings:

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);
}
  1. index.js settings under the store file:

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()  //手动刷新才能生效
      };
    }
}

storage.js file:

/*获取*/
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));
}
  1. Points to note:

Using themeify to change the skin will pack all the corresponding theme styles, and the file size will be large, which is not very friendly (if there are many skins, it is not recommended to use, the style file will be very large) .

  1. Recommended usage:

You can define different theme styles in the component, and then import the corresponding theme file.

variable.scss file: define the color (there is a global color, you can define a global color variable separately).

$bodyBg:rgba(26,57,150,.34);

index.scss file:

@import ‘全局颜色变量’;
@import 'variable';/*当前组件对应颜色变量*/
body{
    background-color:$bodyBg;
}

Import the corresponding theme file in the xx.vue component:

/***导入对应主题样式 */
import(`./${store.state.themeType}/css/index.scss`);

Guess you like

Origin blog.csdn.net/pinhmin/article/details/128671054