前提概要
公司项目的一个需求,根据不同的域名,展示不同的主题,个人感觉这个功能很类似于网页的换肤功能。
大致想法是,先进行预设方案,然后根据不同的域名展示不同的主题,大概的思路是给html标签设置一个data-theme属性,Sass根据对应的属性值,判断使用不同的主题。
一、下载配置Scss
- 安装依赖
yarn add node-sass --dev
yarn add sass-loader --dev
- 使用scss
<style lang="scss" scoped>
</style>
二、全局引入Scss文件配置的预设主题
- 安装 sass-resources-loader
yarn add sass-resources-loader --dev
- 在 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({
resources: ['./src/assets/theme/themes.scss']
})
.end()
})
},
不同的版本配置方式可以参考官网
sass-resources-loader
三、不同主题实现
- 创建 theme.scss 文件,配置不同的配色方案
// ele和ant 只是示例
// 可以添加多种配色方案
$themes: (
ele: (
// 背景色
background_main: #5242FF,
background_deep: #3021D3,
// 字体颜色
font_light: #5242FF,
font_title: #5C54FF,
// 边框
border_light: #5242FF,
border_down_arrow: #5242FF,
// 阴影
shadow_light: #CECAFF,
// 背景图
background_sms: url("./../../assets/images/ele/bg_result.png"),
image_recharge: url("./../../assets/images/ant/img_success.png"),
),
ant: (
// 背景色
background_main: #0B6E51,
background_deep: #094131,
// 字体颜色
font_light: #0B6E51,
font_title: #0B6E51,
// 边框
border_light: #0B6E51,
border_down_arrow: #0B6E51,
// 阴影
shadow_light: #CAFFD0,
// 背景图
background_sms: url("./../../assets/images/ele/bg_result.png"),
image_recharge: url("./../../assets/images/ant/img_success.png"),
)
);
先定义一个 map-$themes 用来存放对应的主题。
- 在 theme.scss 中操作 $theme 变量
// 遍历主题map
@mixin themeeach {
@each $theme-name, $theme-map in $themes {
$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 themeeach {
background-color: themed($color)!important;
}
}
// 获取字体颜色
@mixin font_color($color) {
@include themeeach {
color: themed($color) !important;
}
}
// 获取边框颜色
@mixin border_color($color) {
@include themeeach {
border-color: themed($color) !important;
}
}
// 获取向下三角形
@mixin border_down_arrow($color) {
@include themeeach {
border-color: transparent transparent themed($color) themed($color) !important;
}
}
// 获取阴影颜色
@mixin shadow_light_color($color) {
@include themeeach {
box-shadow: 0 2px 6px 0 themed($color) !important;
}
}
// 获取首页背景图
@mixin background_img($color) {
@include themeeach {
background: themed($color) center top no-repeat;
}
}
// 获取充值成功图片
@mixin image_recharge($color) {
@include themeeach {
background: themed($color) center top no-repeat;
}
}
themeeach 方法用来获取 html 的 data-theme 值
themed 根据传过来的 key 值,获取 theme.scss 中对应的颜色主题
- 在vue中使用
<style lang="scss" scoped>
@import "@/style/_handle.scss";
.header {
font-size: 18px;
@include font_color("font_title");
@include background_color("background_main");
@include border_color("border_light");
}
</style>
- 换肤功能
上面几步已经基本完成了对不同主题色的获取,项目需求是根据不同域名切换,目前就是根据域名判断后,给html标签设置不同的 data-theme 属性值。动态更换主题跟这个功能类似。
changeTheme (theme) {
window.document.documentElement.setAttribute('data-theme', theme)
}
四、后记
这样的方式,实现简单的更换主题可以,但是如果图片过多的话,可以选择根据不同的打包命令,分别打包不同主题下的图片进行输出,这样打包完成后的静态资源会少一些,这个模块我本人还在实现中,后续补充上来。
网友评论