_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;
}
}
}
_themes.scss文件:颜色定义都在这里
$themes:(
theme_1:(
bodyBg:#0b1651,
fontColor: #0de1f6,
borderColor:#0de1f6
),
theme_2:(
bodyBg:#000,
fontColor: #2e85fe,
borderColor:#2e85fe
)
);
使用示例:
引入“_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>
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);
}
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));
}
注意要点:
使用themeify换肤,会把所有的对应主题样式都打包进来,文件容量会很大,不太友好(如果皮肤很多种,不建议使用,样式文件会很大)。
推荐使用方法:
可以组件内定义不同主题样式,再去导入对应主题文件。
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`);