方案一:基于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,})})},
