vue项目利用sass来切换主题
日期: 2019-11-06 分类: 跨站数据 301次阅读
因工作原因,遇到了这个问题,翻查了资料,终于整出来啦,结果符合预期,特此与大家共分享
简介
看到这篇文章,大概率你是个前端工作者,css肯定很熟悉,sass或者less应该也用过(嗯,我就当你用过了),不然我没法写了啊,需要大家稍微理解sass中的一些语法,比如
@mixin 混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,偷懒神器,但是很容易导致滥用,导致代码臃肿
@include 用于引用混合样式,格式是在其后添加混合名称,以及需要的参数
$命名的变量 最普遍的用法,变量以美元符号开头,赋值方法与 CSS 属性的写法一样
知道这些差不多已经够用啦,想了解更多,更详细的同学,可以扒拉扒拉sass的官网 sass官网 当然你还需要了解css的自定义属性
<html data-theme="white"></html>
html{
color: blue;
[data-theme = 'white'] {
color: red;
}
}
如代码所示,这样生效的是自定义属性,而且是优先生效,即
html{
[data-theme = 'white'] {
color: red;
}
color: blue;
}
生效的依然是我们定义的自定义属性,好了普及完毕,接下来进入正题
自定义属性设置
首先我们先设置一下自定义属性,这里我们把自定义属性设置到html根节点上,
//若本地存在主题则应用该主题,否则默认白色主题
currentTheme: localStorage.getItem('DATA-THEME') ? localStorage.getItem('DATA-THEME'): 'white'
setAttribute(theme) {
//给html节点设置自定义属性
window.document.documentElement.setAttribute('data-theme', theme)
//本地存下来用户设置的主题
localStorage.setItem('DATA-THEME', theme)
}
当用户选择主题背景时,我们就来动态的设置下我们的自定义属性,当然我们可以把它写进vuex里面当做全局来用,这样当组件内部需要主题的属性值时,我们也可以取到。
定义我们的sass mixin
这里我们新建一个文件夹叫做theme,放在assets下,在建两个scss文件,如图
theme.scss 这里存放我们的全局配置颜色值,方便管理和维护
// 导入配置
@import "./theme-mixin.scss";
/*-------------------------全局----------------------*/
$color_green: #00b478; // 绿
$color_red: #eb444e; // 红
$color_border: #e4e9eb; // 分割线滚动条
$color_font: #101b21; // 一级字体
$color_font2: #58707b; // 二级字体
$color_font3: #9ab2bc; // 三级字体
$color_bg: #ffffff; // 卡片背景
$color_bg2: #f5f8f9; // 全局背景
$color_bg3: transparent; // 透明
/*-------------------------全局----------------------*/
一半情况下,这样足够我们使用了,但是,架不住设计师们脑洞啊,有的是组件特有怎么办,或者对现有项目进行主题切换,颜色值特乱。
为了防止这种情况,我们可以在配置里面分路由模块进行颜色值添加,因为路由模块肯定是不一样的,这样就算多人协作开发也不会互相影响,也能解决各个组件内的问题
/*-------------------------home----------------------*/
// 白色主题
$home_white_font_color: #000;
$home_white_bg_color: #000;
// 黑色主题
$home_black_font_color: #fff;
$home_black_bg_color: #fff;
/*-------------------------home----------------------*/
这样写,哪个主题的颜色就能很快找到,字体的font,背景的bg,还有边框border,虽然会重复书写好多颜色值,但是一目了然,而且方便后期维护,以及后期添加的新主题。
theme-mixin.scss 这里则写着我们的css逻辑
/* --------------------------------设置字体大小---------------------- */
@function pxTorem($px) { //只需要设置下根节点的$root_font_size就可以把px转成rem
@return $px / $root_font_size+rem;
}
/* ----------------------------------设置字体大小------------------- */
/* --------------------------------设置字体颜色---------------------- */
@mixin font_color(
$font_color_black, //黑色主题时字体颜色
$font_color_white, //白色主题时字体颜色
$font_weight_black: normal, //是否需要加粗
$font_weight_white: normal //是否需要加粗
) {
// 主题为黑色时的字体颜色
[data-theme="black"] & { //记住这里一定要有 & 符号,否则样式不生效
color: $font_color_black;
font-weight: $font_weight_black;
}
// 主题为白色时的字体颜色
[data-theme="white"] & {
color: $font_color_white;
font-weight: $font_weight_white;
}
}
/* ----------------------------------设置字体颜色------------------- */
/* --------------------------------设置背景颜色---------------------- */
@mixin bg_color($bg_color_black, $bg_color_white) {
// 主题为黑色时的背景颜色
[data-theme="black"] & {
background-color: $bg_color_black;
}
// 主题为白色时的背景颜色
[data-theme="white"] & {
background-color: $bg_color_white;
}
}
/* ----------------------------------设置背景颜色------------------- */
好了,逻辑写完了,我们只需要在改变主题的scss文件里,引入我们配置的theme.scss就行,
//设置字体,当然不需要加粗的时候,不需要写后两个参数,以为我们写了noamal默认值
@include font_color($exchange_font_color_white, $exchange_bg_color_black, normal, bold);
//设置字体,传入黑色主题的背景颜色和白色主题的背景颜色
@include bg_color($exchange_bg_color_black, $exchange_bg_color_white);
这样我们就能改变主题啦,但是又有一个问题出现了,细心的同学发现了,我们颜色表里配置的还有border的颜色,这怎么办,难不成又要写一个border的混入?万一它不是border,而是border-right或者left单一的呢?还有万一我需要加权重!important怎么办?这里,笔者写了一个适用于这些的混入,如下
/* --------------------------------自定义设置属性---------------------- */
//第一个为属性值,第二个为黑色主题时的颜色,第三个参数为白色主题时的参数,最后一个参数为接受不确定的参数个数,类似于reset参数
@mixin setAttribute($attribute, $bg_color_black, $bg_color_white, $value...) {
// 主题为黑色时的背景颜色
[data-theme="black"] & {
#{$attribute}: $bg_color_black $value; //#{}为插值语法解析成字符串 多用在属性值以及选择器上比如#{border}-right: 1px solid #fff;
}
// 主题为白色时的背景颜色
[data-theme="white"] & {
#{$attribute}: $bg_color_white $value;
}
}
/* ----------------------------------自定义设置属性------------------- */
那么该怎么用呢?
//以此传入属性值,颜色值,以及其余配置,当然最后一个参数也可以省略不写
//当参数为多个时
@include setAttribute(border, transparent, $exchange_font_color_white3, 1px solid);
//当参数为加权时
@include setAttribute(background, transparent, $exchange_font_color_white3, !important);
//当无参数时
@include setAttribute(background, transparent, $exchange_font_color_white3);
//当颜色值为渐变时
@include setAttribute(border, linear-gradient(#14232a,#16252d,#16262e), $exchange_font_color_white3, 1px solid);
//当有背景图片时 当没有属性值时或者采用默认属性值时,置为空即可
@include setAttribute(background, url('~@/assets/1.png') no-repeat center, '')
当然这种方法也兼容上面的字体颜色设置以及背景设置,ok,大功告成。
嗯,好虽好但是每个组件都引入下,不得累死个人呀,sass有没有类似于vue的混入呢,混入到每一个组件内,答案当然是有的。
使用sass-resources-loader实现全局混入
首先肯定是安装了,执行yarn add sass-resources-loader -D
进行安装。接下来是重点。就是我们还需要配置一下loader,在vue.config.js里面
chainWebpack: config => {
const oneOfsMap = config.module.rule('scss').oneOfs.store;
oneOfsMap.forEach(item => {
item
.use('sass-resources-loader')
.loader('sass-resources-loader')
.options({
// Or array of paths
resources: [
'src/assets/scss/theme-mixin.scss',
'src/assets/scss/theme-var.scss'
]
})
.end();
});
}
现在就可以在任意组件内使用定义好的混入mixin以及全局sass变量了
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐