方案一:基于JS+行内样式
优点:简单易上手,theme.js中可直观看见所有页面中需替换更改的属性值
缺点:若样式差别较大,灵活变改成本高
- 第一步:store中建立模块 theme.js
import $request from '@/fetch/request'
const state = {
toggle: false,
// 通过 state.themeMap[currentCrop] 获取当前主色调
themeMap: {
citrus: {
mainColor: '#FF9A3E',
module: {
home: { // home页面需要随主题改变的颜色和图片
resultBgColor: '#FFF3E7',
homeTopBg: require('@/static/images/topBar/bg_hone_top_citrus.png'),
},
},
},
bamboo: {
mainColor: '#23A041',
module: {
home: {
resultBgColor: '#DEF6E4',
homeTopBg: require('@/static/images/topBar/bg_hone_top_bamboo.png'),
},
},
},
},
currentCrop: 'citrus', // 作物主要包含柑橘、竹、茶
}
const actions = {}
const mutations = {
// 更新当前作物
UPDATE_CURRENT_CROP(state, payload) {
state.currentCrop = payload
}
}
const getters = {
currentTheme(state) {
return state.themeMap[state.currentCrop]
},
}
export default {
name: 'theme',
state,
actions,
mutations,
getters,
}
- 第二步:页面使用
<template>
<view class="course-page">
<!-- 内容区域 -->
<view class="content-area" :style="{ background: currentTheme.mainColor }">
</view>
</view>
</template>
<script>
import { mapGetters, mapState } from 'vuex'
export default {
computed: {
...mapGetters(['currentTheme']),
},
}
</script>
方案二:基于SCSS ,通过控制顶层class取不同样式
优点:可灵活自定义各种主题样式
缺点:过程复杂,可读性稍差
- 第一步:style中建立文件夹 theme,创建varible.scss
// 这个文件主要存放定义的公共全局变量
// 颜色变量表
$citrus-color: #ff9a3e;
$bamboo-color: #23a041;
$tea-color: #a8df4b;
- 第二步:创建themeVarible.scss
// 单独定义不同主题下的属性
@import './varible.scss';
$themes: (
// 主题 橘
citrus:
(
theme-home-top-bg: '@/static/images/topBar/bg_hone_top_citrus.png',
),
// 主题 竹
bamboo:
(
theme-home-top-bg: '@/static/images/topBar/bg_hone_top_bamboo.png',
),
// 主题 茶
tea:
(
theme-home-top-bg: '@/static/images/topBar/bg_hone_top_tea.png',
)
);
- 第三步:创建themeMixin.scss
// 工具
@import './themeVarible.scss';
//取出主题色
@mixin themify($themes) {
// $theme-name, $map 属于 $themes
@each $theme-name,
$map in $themes {
// 将变量定义为全局 此时$map值为例中theme-home-top-bg
$myMap: $map !global;
//新定义一个类
// 这里$theme-name取出来的值为citrus 、 bamboo 、 tea
.theme-#{$theme-name} {
@content;
}
}
}
//从主题色map中取出对应颜色
@function themed($key) {
// $key为传入的变量名
@return map-get($myMap, $key)
}
- 第四步:创建themify.scss
// 混合及混合应用
@import './themeVarible.scss';
@import './themeMixin.scss';
//全局类 使用混合方法
@include themify($themes) {
// 公用类
.theme-home-top-bg {
//themed(...)直接用方法取出对应变量即可
background: url(themed(theme-home-top-bg)) no-repeat;
background-size: 100vw;
}
}
- 单独页面中使用
// 页面单独使用也需要引入themify.scss 全局使用如下,则无需多次引入
@import '@/styles/theme/themify.scss';
@include themify($themes) {
// 同公用类使用方法相同
.theme-home-top-bg {
//themed(...)直接用方法取出对应变量即可
background: url(themed(theme-home-top-bg)) no-repeat;
background-size: 100vw;
}
}
- 全局引入主题函数 uni.app方案
// 直接在 uni.scss文件内引入
@import "@/styles/theme/themify.scss";
- 全局引入主题函数备用方案 vue.config.js
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `@import "@/styles/theme/themify.scss";`, //注意“;”是必须的"
},
},
}
}
小程序底部tab主题切换
changeTabBar() {
import('!!raw-loader!./pages.json').then((r) => {
// import('!!raw-loader!./pages.json') 以字符串读取pages.json文件
const pagesJson = JSON.parse(r.default)
pagesJson.tabBar.list.forEach((item, index) => {
uni.setTabBarItem({
index: index, // tab下标
selectedIconPath: item.selectedIconPath.replace(/_[a-zA-Z0-9]+_/, `_${this.crop}_`), // 选中icon地址
pagePath: item.pagePath,
iconPath: item.iconPath,
text: item.text,
})
})
uni.setTabBarStyle({
selectedColor: this.currentTheme.mainColor,
})
})
},