如何优雅的实现复杂的主题换肤功能
前端必备技能 -- 主题换肤功能
在一个平静的加班夜里,正在工位上摸鱼的小刘;突然公司领导冷不丁的出现在小刘身边,说了一句让小刘头皮发麻的话:“
小刘啊!我刚刚想,我们公司那个软件加一个换肤功能会不会好看些啊?
”小刘的内心虽然已经开始逐渐抓狂,但是表面上还是得大力赞赏领导的这个奇思妙想;今夜注定是一个属于小刘的漫漫长夜~
第一章 拯救小刘之从安装scss做起
如果你项目在构建的时候就选择了scss可以直接下一章哦
1、首先检查下看下你原先的项目安装scss没,如果没有还不快帮小刘安装scss;
npm install node-sass sass-loader --save-dev
2、既然安装了scss,那就去webpack.base.config.js当中的rules添加scss规则;
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass'v]
}
3、在vue中使用scss小刘应该咩问题吧!但还是把格式写一下吧!
<style lang='scss' scoped>
</style>
第二章 拯救小刘之搭建主题对象
在styles文件夹里创建_theme.scss文件;这个动态切换主题是利用data-theme属性在HTML元素最顶层的body或者HTML上设置,data-theme = "_theme.scss里提前设置的主题色库" 这个属性的;最后用 window.document.documentElement.setAttribute( "data-theme", _theme.scss里提前设置的主题色库);来达到主题的切换功能的;
// 在_theme.scss文件内部创建两个测试用的主题方案,data-theme=“小刘设置主题方案”;
// 其中要注意的就是,每套你设置的方案颜色、种类多少都可以自定义,但是要保证每套方案的key都一样才不会造成后期紊乱;
// 主题模板必须放置在$themes当中;
$themes: (
themeRed: (
//字体
font_color1: #373737,
font_color2: #ec4141,
//背景
background_color1: #ec4141,
// 边框
border_color1: #ec4141,
),
themePick: (
//字体
font_color1: #373737,
font_color2: #ff7a9e,
//背景
background_color1: #ff7a9e,
// 边框
border_color1: #ff7a9e,
),
)
第三章 拯救小刘之配置scss混入器
在styles文件夹里再创建一个_handle.scss文件来防止scss混入器,操作_theme.scss里小刘之前设置的主题模板
@import "./_themes.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
@function themed($key) {
@return map-get($theme-map, $key);
}
//获取背景颜色
@mixin background_color($color) {
@include themeify {
background-color: themed($color)!important;
}
}
//获取字体颜色
@mixin font_color($color) {
@include themeify {
color: themed($color)!important;
}
}
//获取边框颜色
@mixin border_color($color) {
@include themeify {
border-color: themed($color)!important;
}
}
上面我只定义了三个比较常规的背景色,边框色,字体色的主题色更换,你想再增多可以继续往下额外添加即可;
第四章 拯救小刘之组件内使用
组件内使用,也很简单先引入_handle.scss,后用@include来设定背景、边框、字体颜色等
<style lang="scss" scoped>
@import '@/styles/_handle.scss';
.el-header {
@include background_color("background_color1"); // 主题背景色
@include font_color("font_color2"); // 主题色
border: 1px solid #000;
@include border_color("border_color1"); // 主题颜色的边框
}
</style>
// 注意,设置边框时,保留原先的border设置,在下面添加@include边框主题色覆盖;
第五章拯救小刘之动态切换主题功能
1、在HTML或Body顶层元素上设置data-theme
<html lang="zh-CN" data-theme="themeRed">
2、template里面设置颜色更改,传递主题色索引号
<div v-for="(item,index) in colorThemList" :key="index" class="small-box">
<div :style="{backgroundColor:item}" :data-index="index" @click="changeColorFn">
<svg v-show="index === isShowIconIndex" slot="reference" class="icon set-icon right-icon" aria-hidden="true">
<use xlink:href="#icon-danxuan-xuanzhong" />
</svg>
</div>
</div>
3、点击对应主题,传回索引值,更改全局主题色
changeColor(index) {
if (index === 0) {
window.document.documentElement.setAttribute('data-theme', 'themeRed')
} else if (index === 1) {
window.document.documentElement.setAttribute('data-theme', 'themePick')
}
}
4、接下来,你的css样式初选以下属性就表示成功啦~
[data-theme=themeGreen4] .el-header {
background-color: #3e7972 !important;
}
终章 拯救小刘计划成功
小刘望着眼前随着自己点击而不断变换颜色的主题,心中不免开始愉悦了起来,~ “我这么能干,会不会给老板看中,从此走上升任总经理、迎娶白富美、走上人生巅峰的王大锤之路啊!!!”
想想就让人开心~~💯
转载自:https://juejin.cn/post/7199537072301457465