方案一:基于JS+行内样式

优点:简单易上手,theme.js中可直观看见所有页面中需替换更改的属性值
缺点:若样式差别较大,灵活变改成本高

  • 第一步:store中建立模块 theme.js
  1. import $request from '@/fetch/request'
  2. const state = {
  3. toggle: false,
  4. // 通过 state.themeMap[currentCrop] 获取当前主色调
  5. themeMap: {
  6. citrus: {
  7. mainColor: '#FF9A3E',
  8. module: {
  9. home: { // home页面需要随主题改变的颜色和图片
  10. resultBgColor: '#FFF3E7',
  11. homeTopBg: require('@/static/images/topBar/bg_hone_top_citrus.png'),
  12. },
  13. },
  14. },
  15. bamboo: {
  16. mainColor: '#23A041',
  17. module: {
  18. home: {
  19. resultBgColor: '#DEF6E4',
  20. homeTopBg: require('@/static/images/topBar/bg_hone_top_bamboo.png'),
  21. },
  22. },
  23. },
  24. },
  25. currentCrop: 'citrus', // 作物主要包含柑橘、竹、茶
  26. }
  27. const actions = {}
  28. const mutations = {
  29. // 更新当前作物
  30. UPDATE_CURRENT_CROP(state, payload) {
  31. state.currentCrop = payload
  32. }
  33. }
  34. const getters = {
  35. currentTheme(state) {
  36. return state.themeMap[state.currentCrop]
  37. },
  38. }
  39. export default {
  40. name: 'theme',
  41. state,
  42. actions,
  43. mutations,
  44. getters,
  45. }
  • 第二步:页面使用
  1. <template>
  2. <view class="course-page">
  3. <!-- 内容区域 -->
  4. <view class="content-area" :style="{ background: currentTheme.mainColor }">
  5. </view>
  6. </view>
  7. </template>
  8. <script>
  9. import { mapGetters, mapState } from 'vuex'
  10. export default {
  11. computed: {
  12. ...mapGetters(['currentTheme']),
  13. },
  14. }
  15. </script>

方案二:基于SCSS ,通过控制顶层class取不同样式

优点:可灵活自定义各种主题样式
缺点:过程复杂,可读性稍差

  • 第一步:style中建立文件夹 theme,创建varible.scss
  1. // 这个文件主要存放定义的公共全局变量
  2. // 颜色变量表
  3. $citrus-color: #ff9a3e;
  4. $bamboo-color: #23a041;
  5. $tea-color: #a8df4b;
  • 第二步:创建themeVarible.scss
  1. // 单独定义不同主题下的属性
  2. @import './varible.scss';
  3. $themes: (
  4. // 主题 橘
  5. citrus:
  6. (
  7. theme-home-top-bg: '@/static/images/topBar/bg_hone_top_citrus.png',
  8. ),
  9. // 主题 竹
  10. bamboo:
  11. (
  12. theme-home-top-bg: '@/static/images/topBar/bg_hone_top_bamboo.png',
  13. ),
  14. // 主题 茶
  15. tea:
  16. (
  17. theme-home-top-bg: '@/static/images/topBar/bg_hone_top_tea.png',
  18. )
  19. );
  • 第三步:创建themeMixin.scss
  1. // 工具
  2. @import './themeVarible.scss';
  3. //取出主题色
  4. @mixin themify($themes) {
  5. // $theme-name, $map 属于 $themes
  6. @each $theme-name,
  7. $map in $themes {
  8. // 将变量定义为全局 此时$map值为例中theme-home-top-bg
  9. $myMap: $map !global;
  10. //新定义一个类
  11. // 这里$theme-name取出来的值为citrus 、 bamboo 、 tea
  12. .theme-#{$theme-name} {
  13. @content;
  14. }
  15. }
  16. }
  17. //从主题色map中取出对应颜色
  18. @function themed($key) {
  19. // $key为传入的变量名
  20. @return map-get($myMap, $key)
  21. }
  • 第四步:创建themify.scss
  1. // 混合及混合应用
  2. @import './themeVarible.scss';
  3. @import './themeMixin.scss';
  4. //全局类 使用混合方法
  5. @include themify($themes) {
  6. // 公用类
  7. .theme-home-top-bg {
  8. //themed(...)直接用方法取出对应变量即可
  9. background: url(themed(theme-home-top-bg)) no-repeat;
  10. background-size: 100vw;
  11. }
  12. }
  • 单独页面中使用
  1. // 页面单独使用也需要引入themify.scss 全局使用如下,则无需多次引入
  2. @import '@/styles/theme/themify.scss';
  3. @include themify($themes) {
  4. // 同公用类使用方法相同
  5. .theme-home-top-bg {
  6. //themed(...)直接用方法取出对应变量即可
  7. background: url(themed(theme-home-top-bg)) no-repeat;
  8. background-size: 100vw;
  9. }
  10. }
  • 全局引入主题函数 uni.app方案
  1. // 直接在 uni.scss文件内引入
  2. @import "@/styles/theme/themify.scss";
  • 全局引入主题函数备用方案 vue.config.js
  1. module.exports = {
  2. css: {
  3. loaderOptions: {
  4. scss: {
  5. prependData: `@import "@/styles/theme/themify.scss";`, //注意“;”是必须的"
  6. },
  7. },
  8. }
  9. }

小程序底部tab主题切换

  1. changeTabBar() {
  2. import('!!raw-loader!./pages.json').then((r) => {
  3. // import('!!raw-loader!./pages.json') 以字符串读取pages.json文件
  4. const pagesJson = JSON.parse(r.default)
  5. pagesJson.tabBar.list.forEach((item, index) => {
  6. uni.setTabBarItem({
  7. index: index, // tab下标
  8. selectedIconPath: item.selectedIconPath.replace(/_[a-zA-Z0-9]+_/, `_${this.crop}_`), // 选中icon地址
  9. pagePath: item.pagePath,
  10. iconPath: item.iconPath,
  11. text: item.text,
  12. })
  13. })
  14. uni.setTabBarStyle({
  15. selectedColor: this.currentTheme.mainColor,
  16. })
  17. })
  18. },