vue实现换肤及避免的坑

  1. _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;
    }
  }
} 
  1. _themes.scss文件:颜色定义都在这里

$themes:(
  theme_1:(
    bodyBg:#0b1651,
    fontColor: #0de1f6,
    borderColor:#0de1f6
  ),
  theme_2:(
    bodyBg:#000,
    fontColor: #2e85fe,
    borderColor:#2e85fe 
  )
);
  1. 使用示例:

引入“_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>
  1. 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);
}
  1. store文件下的index.js设置:

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文件:

/*获取*/
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. 注意要点:

使用themeify换肤,会把所有的对应主题样式都打包进来,文件容量会很大,不太友好(如果皮肤很多种,不建议使用,样式文件会很大)

  1. 推荐使用方法:

可以组件内定义不同主题样式,再去导入对应主题文件。

variable.scss文件:定义颜色(有全局颜色,可以单独定义一份全局颜色变量)。

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

index.scss文件:

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

xx.vue组件内导入对应主题文件:

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值