uniapp 中实现主题色配置切换

3,747 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

前言

由于最近准备用 uniapp 开发一个新项目 pad 端的 app 项目,并且需要根据不同的子品牌实现一个换肤功能,于是尝试做了一个 uniapp 主题色切换的插件

需求

实现一个通用的theme类,配合<page>页面组件完成整个应用主题色配置,后续项目有类似需求可以直接套用

思路

通过在根组件配置相应主题的类名,以此修改组件内所有样式类的主题色

image-20221208172657797

实现

定义主题颜色变量

修改uni.scss

/* 主题色 */
$default-theme: red;
$tx-theme: blue;
​
$white-text-color: #ffffff;

配置主题风格类

新建style文件夹,将类维护在一个 index.scss 文件中

.default-theme {
  .theme-bg {
    background-color: $default-theme;
  }
  .theme-btn {
    background-color: $default-theme;
    color: $white-text-color;
  }
}
​
.tx-theme {
  .theme-bg {
    background-color: $tx-theme;
    color: $white-text-color;
  }
  .theme-btn {
    background-color: $tx-theme;
    color: $white-text-color;
  }
}

引入项目 App.vue

<style lang="scss">
  /*每个页面公共css */
  @import "style/index.scss";
</style>

创建页面容器组件

新建 page.vue 组件,作为所有页面的根组件,并在里面实现样式的切换逻辑

<template>
  <view class="default-theme">
    <slot></slot>
  </view>
</template>

做一个 demo.vue 页面测试

<template>
  <page>
    <view class="theme-bg">
      <text>测试</text>
    </view>
    <br>
    <button class="theme-btn" @tap="test">请求</button>
  </page>
</template>

image-20221208155658220

可以看到我们配置的默认主题样式default-theme在页面中已经生效了,接下来只要切换根组件的样式类名,就可以实现切换效果了

主题切换方法

我们编写一个主题类,里面保存了我们的默认样式,并提供获取样式名,修改样式名的方法

import { ref } from 'vue'class Theme {
  constructor() {
    this.theme = ref('default-theme')
  }
  
  get = () => {
    return this.theme.value
  }
  
  change = (name) => {
    this.theme.value = `${name}-theme`
  }
}
​
export default Theme

全局注册

修改 main.js,将主题方法挂在 uni 对象上

import Theme from '@/lib/theme/index.js'const theme = new Theme()
uni.$theme = theme

根组件样式配置

<template>
  <view :class="theme">
    <slot></slot>
  </view>
</template><script>
  export default {
    computed: {
      theme: () => {
        return uni.$theme.get()
      }
    }
  }
</script>

demo页面测试切换

methods: {
  change() {
    uni.$theme.change('tx') 
  }
}

63f217cea0f85a8c163a7e881255ce0c-Kapture 2022-12-08 at 16.43.05 (1)

数据持久化

这样一个主题切换的功能就实现了,但还有个小点,一般主题配置我们需要做本地缓存,我们把主题配置放在 storage

完整代码

  • Theme.js
import { ref } from 'vue'class Theme {
  constructor() {
    this.theme = ref(null)
    this.init()
  }
  
  init = () => {
    const theme = uni.getStorageSync('theme') || 'default-theme'
    this.theme.value = theme
    uni.setStorageSync('theme', theme)
  }
  
  get = () => {
    return this.theme.value
  }
  
  change = (name) => {
    this.theme.value = `${name}-theme`
    uni.setStorageSync('theme', `${name}-theme`)
  }
}
​
export default Theme
  • Page.vue
<template>
  <view :class="theme">
    <slot></slot>
  </view>
</template><script>
  export default {
    computed: {
      theme: () => {
        return uni.$theme.get()
      }
    }
  }
</script>