vue使用sass实现主题换肤功能

20 篇文章 0 订阅

本文只介绍深浅两种主题换肤作为参考。

1.创建配置动态样式的scss文件,路径为/src/assets/scss/_theme.scss。

$themes: (
    light: (
        //字体
        font_color1: #000,
        //背景
        background_color1: #fff,
        // 背景渐变
        background_gradient1:#F8FBFD ,
        //边框
        border_color1: #e8ebf0,
        //边框阴影
        box_shadow_color1: rgba(127, 131, 168, 0.2)
    ),
    dark: (
        //字体
        font_color1: #fff,  
        //背景
        background_color1: #000,
        //背景渐变
        background_gradient1:#DD1C1C,
        //边框
        border_color1: #34383c,
        // 阴影
        box_shadow_color1: rgba(0, 0, 0, 0.4)
    ),
);

2.创建样式封装的scss文件,路径为/src/assets/scss/_handle.scss。

@import "./_theme.scss";

//遍历主题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 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) !important;
    }
}
//获取阴影颜色
@mixin box_shadow($color) {
    @include themeify {
        box-shadow: 0px 2px 4px 0px themed($color) !important;
    }
}
// 获取背景色渐变
@mixin linear-gradient($from, $to) {
    @include themeify {
      background: linear-gradient(to bottom, themed($from),themed($to));
    }
}
/*px转rem*/
@mixin px2rem($property,$px,$px2:false,$px3:false,$px4:false){
	$rem:75px;/* 设计稿尺寸/10 */
  @if $px and $px2 and $px3 and $px4 {
    #{$property}: ($px / $rem) + rem ($px2 / $rem) + rem ($px3 / $rem) + rem ($px4 / $rem) + rem;
  }
  @else if $px and $px2 {
		#{$property}: ($px / $rem) + rem ($px2 / $rem) + rem;
		//[data-model='pad'] & {#{$property}: ($px * 1.4 / $rem) + rem ($px2 * 1.4 / $rem) + rem;}
	}
	@else{
		#{$property}: ($px / $rem) + rem!important;
		//[data-model='pad'] & {#{$property}: ($px * 1.4 / $rem) + rem;}
	}
}
 
/*根据dpr计算font-size*/
@mixin font-dpr($font-size){
	font-size: $font-size;
	//[data-model="pad"] & { font-size: $font-size * 1.4; }
	[data-dpr="2"] & { font-size: $font-size * 2;}
	[data-dpr="3"] & { font-size: $font-size * 3;}
}
 
/*弹性盒属性*/
%flexbox{
	display: inline-flex;display: -webkit-flex;display: flex;
}
/*弹性盒比例*/
@mixin flex($num:1){
	-webkit-box-flex:$num;-moz-box-flex:$num;-webkit-flex:$num;-ms-flex:$num;flex:$num;
}
/*超行溢出显示省略号*/
@mixin overflow($num:1,$fontSize:0,$lineHeight:1.5){
  display: -webkit-box;-webkit-line-clamp:$num; overflow: hidden;
  /*! autoprefixer: off */
  -webkit-box-orient: vertical;
  /* autoprefixer: on */
  @if $fontSize!=0 and $lineHeight{/*高度需要撑开*/
    line-height:$lineHeight;
    @if $lineHeight < 1.2 {
      line-height:1.2; /*最小需要1.2,否则在部分安卓机下第$num+1行会顶部漏出*/
    }
    height: $num * $fontSize * $lineHeight;
    [data-dpr="2"] & { height: $num * $fontSize * $lineHeight * 2!important;}
    [data-dpr="3"] & { height: $num * $fontSize * $lineHeight * 3!important;}
  }
}
 
//transition兼容写法
@mixin transition($content:all .2s){
  -moz-transition: $content;
  -webkit-transition: $content;
  -o-transition: $content;
  transition: $content;
}

//transfrom兼容
@mixin translateX($num:-50%){
  -ms-transform: translateX($num);
  -moz-transform: translateX($num);
  -webkit-transform: translateX($num);
  -o-transform: translateX($num);
  transform: translateX($num);
}

@mixin translateY($num:-50%){
  -ms-transform: translateY($num);
  -moz-transform: translateY($num);
  -webkit-transform: translateY($num);
  -o-transform: translateY($num);
  transform: translateY($num);
}

@mixin rotate($deg:90deg){
  -ms-transform:rotate($deg);
  -moz-transform:rotate($deg);
  -webkit-transform:rotate($deg);
  -o-transform:rotate($deg);
  transform:rotate($deg);
}

3.根据不同的主题颜色设置全局属性

//项目登录/主题更换时调用
//已知type="0"为深色主题,type="1"为浅色主题。
changeTheme(type = 1){
   const themeArr = ['dark', 'light'];
   const themeShow= themeArr [type];
   window.document.documentElement.setAttribute("data-theme", themeShow);
}

4.index.vue中使用

<style lang="scss" scoped>
@import "@/assets/scss/_handle.scss";
span{
      @include font_color("font_color1");
      @include border_color("border_color1");
      @include background_color("background_color1");
      @include box_shadow("box_shadow_color1");
      ...
}
</style>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值